我正在查看StringIO
的源代码,其中有一些注释:
- 使用真实文件通常更快(但不太方便)。
- 还有一个更快的C语言实现,称为
cStringIO
,但它不能被子类化。
StringIO
就像一个内存文件对象,为什么比真实文件对象慢?
这实际上与Python的解释性质无关:BytesIO
和StringIO
都是用Python实现的,但仍然优于文件I/O。
事实上,在StringIO
的理想用例(对空缓冲区的单个写入)下,StringIO
比文件I/O更快。实际上,如果写入足够大,它甚至会胜过cStringIO
。请参见我的问题here。
那么为什么StringIO
被认为是“慢”的呢?StringIO
的真正问题在于其由不可变序列支持,无论是str
还是unicode
。如果您只写一次,这很好理解。但是,正如tdelaney的答案所指出的那样,当随机位置进行写入时,它会变得非常缓慢(例如,10-100倍),因为每次在中间进行写入时,它都必须复制整个支持序列。
BytesIO
没有这个问题,因为它由(可变的)bytearray
支持。同样,cStringIO
会更轻松地处理随机写入。我猜测它在内部违反了不可变性规则,因为C字符串是可变的。
* 无论如何,在_pyio
中的版本是这样的。标准库版本在io
中是用C编写的。
从源代码中并不一定明显,但是Python文件对象是直接建立在C库函数之上的,可能只有一层很小的Python代码来呈现一个Python类,或者甚至是一个C包装器来呈现一个Python类。原生的C库将高度优化以从磁盘读取字节和块。Python的StringIO库则完全由本地Python代码编写 - 这比本地C代码慢。