为什么StringIO对象比真正的文件对象慢?

7

我正在查看StringIO的源代码,其中有一些注释:

  1. 使用真实文件通常更快(但不太方便)
  2. 还有一个更快的C语言实现,称为cStringIO,但它不能被子类化。

StringIO就像一个内存文件对象,为什么比真实文件对象慢?

3个回答

4

这实际上与Python的解释性质无关:BytesIOStringIO都是用Python实现的,但仍然优于文件I/O。

事实上,在StringIO的理想用例(对空缓冲区的单个写入)下,StringIO比文件I/O更快。实际上,如果写入足够大,它甚至会胜过cStringIO。请参见我的问题here

那么为什么StringIO被认为是“慢”的呢?StringIO的真正问题在于其由不可变序列支持,无论是str还是unicode。如果您只写一次,这很好理解。但是,正如tdelaney的答案所指出的那样,当随机位置进行写入时,它会变得非常缓慢(例如,10-100倍),因为每次在中间进行写入时,它都必须复制整个支持序列。

BytesIO没有这个问题,因为它由(可变的)bytearray支持。同样,cStringIO会更轻松地处理随机写入。我猜测它在内部违反了不可变性规则,因为C字符串是可变的。

* 无论如何,在_pyio中的版本是这样的。标准库版本在io中是用C编写的。


好棒的回答,点个赞! - stop.climatechange.now

3
Python的文件处理完全是用C实现的。这意味着它非常快(至少与原生的C代码相同数量级)。
然而,StringIO库是用Python编写的。因此,模块本身是解释的,并伴随着相关的性能损失。
正如你所知道的,还有另一个模块cStringIO,具有类似的接口,可以在对性能敏感的代码中使用。 这个模块不可子类化的原因是因为它是用C编写的。

谢谢你的回答。 - JanuaryStar
@sapi - 有没有类似 BytesIO 的东西? - Don Code

0

从源代码中并不一定明显,但是Python文件对象是直接建立在C库函数之上的,可能只有一层很小的Python代码来呈现一个Python类,或者甚至是一个C包装器来呈现一个Python类。原生的C库将高度优化以从磁盘读取字节和块。Python的StringIO库则完全由本地Python代码编写 - 这比本地C代码慢。


好的 - 重新阅读问题,发现有矛盾之处。需要进行一些小的编辑 - 已完成 :-) - Tony Suffolk 66
抱歉我的英语不好,我的意思是“查看”,而不是“寻找”。 - JanuaryStar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接