我不明白为什么在 Python 2.7 中解析此文件比在 Python 3.6 中解析该文件快得多。我在 macOS 和 Arch-Linux 上都独立发现了这种模式。别人能复制吗?有什么解释吗?
警告:代码片段写入一个 ~2GB 的文件
时间:
$ python2 test.py
5.01580309868
$ python3 test.py
10.664075019994925
test.py
代码:
import os
SEQ_LINE = 'ATCGN'* 80 + '\n'
if not os.path.isfile('many_medium.fa'):
with open('many_medium.fa', 'w') as out_f:
for i in range(1000000):
out_f.write('>{}\n'.format(i))
for _ in range(5):
out_f.write(SEQ_LINE)
from timeit import timeit
def f():
with open('many_medium.fa') as f:
for line in f:
pass
print(timeit('f()', setup='from __main__ import f', number=5))
最佳答案
因为在 Python 2 中,标准的 open()
调用创建一个比 Python 3 open()
调用简单得多的文件对象。 Python 3 open
调用与 io.open()
相同。 ,同样的框架是available on Python 2 .
要使其成为公平比较,您必须将以下行添加到测试的顶部:
from io import open
随着这一变化,Python 2 的时间从 5.5 秒变为 37 秒。与该数字相比,Python 3 在我的系统上运行测试所用的 11 秒确实快得多。
那么这里发生了什么? io
库提供了比旧的 Python 2 file
对象更多的功能:
open()
返回的文件对象包含最多 3 层组合功能,允许您控制缓冲和文本处理。- 支持非阻塞 I/O 流
- 跨各种流的一致界面
- 更多地控制 universal newline translation feature .
- 完全支持 Unicode。
额外的功能是以性能为代价的。
但是您的 Python 2 测试读取字节字符串,换行符总是被翻译成\n
,并且代码正在处理的文件对象非常接近操作系统-提供的文件原语,带有 all the downsides .在 Python 3 中,您通常希望将文件中的数据作为文本进行处理,因此以文本模式打开文件会为您提供一个将二进制数据解码为 Unicode str
对象的文件对象。
那么如何才能让 Python 3 的运行速度“更快”呢?这取决于您的具体用例,但您有一些选择:
- 对于文本模式文件,禁用通用换行符处理,尤其是在处理使用与平台标准不同的行结尾的文件时。将
newline
参数设置为预期的换行字符序列,如\n
。二进制模式只支持\n
作为行分隔符。 - 将文件作为二进制数据 处理,不要解码为
str
。或者,解码为 Latin-1,从字节到代码点的直接一对一映射。当您的数据也是纯 ASCII 时,这是一个选项,其中 Latin-1 省略了对范围为 0-127 而不是 0-255 的字节的错误检查。
当使用 mode='rb'
时,Python 3 可以轻松匹配 Python 2 的时间,在我的系统上测试只需要 5.05 秒,使用 Python 3.7。
使用 latin-1
作为编解码器与 UTF-8(通常的默认值)只有很小的区别; UTF-8 可以非常有效地解码。但它可能会对其他编解码器产生影响。您通常希望显式设置 encoding
参数,而不是依赖于 default encoding used .
关于python - 为什么在 Python 2 中打开和迭代文件句柄的速度比 Python 3 快两倍?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52545269/