【问题标题】:BufferedReader in Python 2.x vs Python 3.xPython 2.x 与 Python 3.x 中的 BufferedReader
【发布时间】:2010-12-25 18:11:36
【问题描述】:

我有一个在 Python 2 和 Python 3 中运行的程序,但速度上存在巨大差异。我知道在 switch 中进行了一些内部更改,但是 io.BufferedReader 的差异非常大。在这两个版本中,我都使用 io.BufferedReader 因为主程序循环一次只需要一个字节的数据。这是脚本的 cProfile 输出的摘录(请参阅 cumtime,而不是 tottime):

Python 2:
 ncalls  tottime  percall  cumtime  percall filename:lineno(function)
 36984   0.188    0.000    0.545    0.000   io.py:929(read)

Python 3:
 36996    0.063   0.000    0.063    0.000   {method 'read' of '_io.BufferedReader' objects}

当我打印对象时,两者都返回 io.BufferedReader 之类的东西,所以我确定它们都在使用 BufferedReader。

Here 是有问题的代码。见第 28 行。调用者负责设置 bufstream。我用bufstream = io.open('testfile', 'rb')

为什么 BufferedReader 读取文件中的单个字节的速度会有如此大的差异,我该如何“修复”Python 2.x 的问题?我正在运行 Python 2.6 和 Python 3.1。

【问题讨论】:

  • 好吧好吧。那么问题是什么?
  • @Eric:根据您的编辑,性能对您来说那么重要吗?
  • @A A ,是的,性能非常重要,这就是我问如何解决问题的原因。在最佳情况下,两个版本的 Python 的吞吐量均为 525 KB/s,但在更典型的情况下,Python 2 的吞吐量为 59KB/s,而 Python 3 的吞吐量为 155KB/s。
  • @Eric:好吧,鉴于数字,我希望有人回答你的问题。
  • @Eric Pruitt:关于您的编辑 2,构造函数 arg stream 是什么?

标签: python performance python-3.x bufferedreader


【解决方案1】:

为了给你一个更完整的答案,你需要查看你的代码(或者,更好的是,你的代码的可执行文件)。

但是可以从您的配置文件输出中收集到部分答案:io.py 建议“Python 2”(为避免疑问,给出实际版本号)正在 Python 中实现 BufferedReader,而_io.BufferedReader 建议“Python3 " 在 C 中实现它。

最新消息:Python 2.6 的 io.py 超过 64Kb,并在前面包含以下评论:

# This is a prototype; hopefully eventually some of this will be
# reimplemented in C.

Python 2.7 的 io.py 大约 4Kb,似乎是 _io 模块的薄包装。

如果您需要 2.6 解决方法的真正帮助,请显示您的代码。

Python 2.6 的可能解决方法

代替:

test = io.open('test.bmp', 'rb')

这样做:

test = open('test.bmp', 'rb')

一些粗略的时序图,包括缺失的链接(Python 2.7):

Windows 7 Pro,32 位,大约 5 Mb 文件,代码内容为:

while 1:
    c = f.read(1)
    if not c: break

2.6: io.open 20.4s, open 5.1s
2.7: io.open  3.3s, open 4.8s # io.open is better
3.1: io.open  3.6s, open 3.6s # effectively same code is used

所以一个更好的故事似乎是这样的:一般来说,除非你有充分的理由,否则不要对 io.open 感兴趣。您希望 2.7 更快。

【讨论】:

  • 代码只是对 io.BufferedReader.read(1) 的调用。我必须调用 .read(1) 的次数各不相同,但我一次只处理一个字节。
  • @John 由调用者来打开流。电话在您回复的 Kabie 的帖子中。在这种情况下,它是一个班轮:test = io.open('test.bmp', 'rb')
  • @Eric Pruitt:一般的想法是使用此类信息编辑您的问题,以便回答者在尝试帮助您时不会阅读所有其他答案的所有 cmets。请参阅我的更新答案。
  • @John,明白了。我认为我使用 io.open 很直观,但我已经更新了我原来的问题。这似乎成功了。我不知道这是否来自过去使用 Python 2.5 的经验(这是我在几天前升级到 Debian Squeeze Beta 2 之前使用最多的),但我认为一个接一个地读取字节是Python 真的很慢。在 Python 2.6 和 Python 3 上使用普通开放增加了吞吐量,尽管后者的吞吐量很小。谢谢!
  • 吞吐量现在在 Python 2.6 上约为 102KB/s,在 Python 3.1 上为 160 KB/s。
【解决方案2】:

使用 2.7 应该可以解决这个问题。请参阅PEP 3116Python 2.7 doc

A part of module io is written in python 在 2.6 中,而在 2.7+ 中 the whole module is written in C

【讨论】:

  • StringIO 和这个有什么关系?我只是在文件上使用 BufferedReader; io.open(filepath, buffering=...).
  • StringIO 与 OP 的问题完全无关。
猜你喜欢
  • 1970-01-01
  • 2010-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多