python - 为什么在 Python 2 中打开和迭代文件句柄的速度比 Python 3 快两倍?

标签 python python-3.x python-2.7 file parsing

我不明白为什么在 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/

相关文章:

Python:将 Json 对象放入队列时出错

python - 属性错误 : 'module' object has no attribute 'celery'

windows - Windows 8 上的 .idlerc 文件夹在哪里?

python:如何/在何处将一个简单的库安装在我计算机上的一个众所周知的地方

python - 反向编辑距离

python - 在 SQLAlchemy ORM 中将对象标记为干净

python-3.x - 如何在pytorch中放大图像?

python - 按下按钮时的PyAudio记录

Python tkinter 在标题栏中更改 'open'

python - 如何在 Tensorflow 上测试自己的图像到 Cifar-10 教程?