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

7 投票
3 回答
3705 浏览
提问于 2025-04-18 22:57

我在查看 StringIO 的源代码时,看到了一些说明:

  1. 使用真实的文件通常会更快(但不太方便)
  2. 还有一个用C语言实现的更快的版本,叫做 cStringIO,但它不能被继承。

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

3 个回答

0

从源代码上看,这可能不是很明显,但Python的文件对象是直接基于C语言的库函数构建的,可能还加了一层小的Python代码来展示成Python类,或者用C语言的包装来呈现成Python类。原生的C语言库在从磁盘读取字节和数据块时会非常高效。而Python的StringIO库完全是用Python代码写的,这比原生的C代码要慢。

4

这其实和Python的解释性特性没什么关系:BytesIOStringIO都是用Python实现的,但BytesIO的速度还是比文件输入输出快。

实际上,在StringIO最理想的使用场景下(就是在一个空的缓冲区开头写一次),StringIO的速度比文件输入输出还要快。如果写入的数据量足够大,它甚至会比cStringIO还快。你可以看看我在这里提问的内容 这里

那么,为什么StringIO会被认为“慢”呢?StringIO真正的问题在于它是由不可变序列支持的,不管是str还是unicode。如果你只写一次,这没什么问题。但正如tdelaney的回答所指出的,当你在随机位置写入时,它的速度会大幅下降(可能慢10到100倍),因为每次在中间写入时,它都需要复制整个支持序列。

BytesIO就没有这个问题,因为它是由一个(可变的)bytearray支持的。同样,cStringIO似乎在处理随机写入时也更轻松。我猜它在内部打破了不可变的规则,因为C语言的字符串是可变的。

* 好吧,_pyio中的版本是这样。标准库中的io版本是用C写的。

3

Python的文件处理功能完全是用C语言实现的。这意味着它的速度非常快,至少和用C写的代码差不多。

不过,StringIO库是用Python写的。因此,这个模块是被解释执行的,所以在性能上会有一些损失。

你可能知道还有一个模块叫cStringIO,它有一个类似的接口,可以在对性能要求高的代码中使用。这个模块不能被继承的原因是因为它是用C语言写的。

撰写回答