在 Python 2.7 中,为什么用文本模式写字符串比用二进制模式写更快?

问题描述 投票:0回答:1

下面的示例脚本将一些字符串写到一个文件中,使用了 "w",文本,或 "wb",二进制模式。

import itertools as it
from string import ascii_lowercase
import time

characters = it.cycle(ascii_lowercase)
mode = 'w'
# mode = 'wb'  # using this mode takes longer to execute
t1 = time.clock()
with open('test.txt', mode) as fh:
    for __ in xrange(10**7):
        fh.write(''.join(it.islice(characters, 0, 50)))
t2 = time.clock()
print 'Mode: {}, time elapsed: {:.2f}'.format(mode, t2 - t1)

在Python 2中,使用 "w" 模式下执行,我发现它在 24.89 +/- 0.02 s 而使用 "wb" 需要 25.67 +/- 0.02 s 来执行。这些是每个模式连续运行三次的具体时间。

mode_w  = [24.91, 24.86, 24.91]
mode_wb = [25.68, 25.64, 25.69]

我对这些结果感到惊讶,因为Python 2无论如何都是把它的字符串作为二进制字符串来存储的,所以既没有 "w" 也不 "wb" 需要执行任何编码工作。而文本模式则需要执行额外的工作,如 检查行尾:

默认情况下,使用文本模式,这可能会转换为 '\n' 写入时将字符转换为特定平台的表示,读取时再转换为特定平台的表示。

所以,如果说我希望文本模式 "w" 比二进制模式耗时更长 "wb". 然而,情况似乎恰恰相反。为什么会这样?


用CPython 2.7.12测试。

python python-2.7 file-io cpython
1个回答
0
投票

从源码上看 file.write 揭示了以下的区别 二进制模式文本模式:

if (f->f_binary) {
    if (!PyArg_ParseTuple(args, "s*", &pbuf))
        return NULL;
    s = pbuf.buf;
    n = pbuf.len;
}
else {
    PyObject *text;
    if (!PyArg_ParseTuple(args, "O", &text))
        return NULL;

    if (PyString_Check(text)) {
        s = PyString_AS_STRING(text);
        n = PyString_GET_SIZE(text);
    }

这里 f->f_binary 的模式时,设置为 open 包括 "b". 在这种情况下,Python从字符串对象中构造一个辅助缓冲区对象,然后获取数据。s 和长度 n 的缓冲区。我想这是为了与其他支持缓冲区接口的对象兼容(通用性)。

这里 PyArg_ParseTuple(args, "s*", &pbuf) 创建相应的 缓冲对象. 这个操作需要额外的计算时间,而在文本模式下工作时,Python只是简单地解析参数 作为一个对象("O") 几乎没有成本。检索数据和长度通过

s = PyString_AS_STRING(text);
n = PyString_GET_SIZE(text);

同时进行 缓冲区创建时.

这意味着在二进制模式下工作时,从字符串对象中创建一个辅助缓冲区对象会带来额外的开销。因此,在二进制模式下工作时,执行时间会更长。

© www.soinside.com 2019 - 2024. All rights reserved.