In Python 2.7 why are strings written faster in text mode than in binary mode?

那年仲夏 提交于 2021-02-11 14:16:37

问题


The following example script writes some strings to a file using either "w", text, or "wb", binary mode:

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)

With Python 2, using "w" mode I found it executes in 24.89 +/- 0.02 s while using "wb" it takes 25.67 +/- 0.02 s to execute. These are the specific timings for three consecutive runs for each mode:

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

I'm surprised by these results since Python 2 stores its strings anyway as binary strings, so neither "w" nor "wb" need to perform any encoding work. Text mode on the other hand needs to perform additional work such as checking for line endings:

The default is to use text mode, which may convert '\n' characters to a platform-specific representation on writing and back on reading.

So if anything I'd expect text mode "w" to take longer than binary mode "wb". However the opposite seems to be the case. Why is this?


Tested with CPython 2.7.12


回答1:


Looking at the source code for file.write reveals the following difference between binary mode and text mode:

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);
    }

Here f->f_binary is set when the mode for open includes "b". In this case Python constructs an auxiliary buffer object from the string object and then gets the data s and length n from that buffer. I suppose this is for compatibility (generality) with other objects that support the buffer interface.

Here PyArg_ParseTuple(args, "s*", &pbuf) creates the corresponding buffer object. This operation requires additional compute time while when working with text mode, Python simply parses the argument as an Object ("O") at almost no cost. Retrieving the data and length via

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

is also performed when the buffer is created.

This means that when working in binary mode there's an additional overhead associated with creating an auxiliary buffer object from the string object. For that reason the execution time is longer when working in binary mode.



来源:https://stackoverflow.com/questions/62161186/in-python-2-7-why-are-strings-written-faster-in-text-mode-than-in-binary-mode

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!