我已经用谷歌搜索并在 SO 上搜索这些缓冲区模块之间的区别。但是,我仍然不太了解,我认为我阅读的一些帖子已经过时了。
在 Python 2.7.11 中,我使用r = requests.get(url)
. 然后我将StringIO.StringIO(r.content)
,cStringIO.StringIO(r.content)
和传递io.BytesIO(r.content)
给了一个为解析内容而设计的函数。
这三种方法都可用。我的意思是,即使文件是二进制文件,使用StringIO
. 为什么?
另一件事是关于他们的效率。
In [1]: import StringIO, cStringIO, io
In [2]: from numpy import random
In [3]: x = random.random(1000000)
In [4]: %timeit y = cStringIO.StringIO(x)
1000000 loops, best of 3: 736 ns per loop
In [5]: %timeit y = StringIO.StringIO(x)
1000 loops, best of 3: 283 µs per loop
In [6]: %timeit y = io.BytesIO(x)
1000 loops, best of 3: 1.26 ms per loop
如上图所示,cStringIO > StringIO > BytesIO
.
我发现有人提到io.BytesIO
总是制作一个新副本,这会花费更多时间。但也有一些帖子提到,这在后来的 Python 版本中已修复。
IO
那么,任何人都可以在最新的 Python 2.x 和 3.x 中对这些 s 进行彻底的比较吗?
我找到的一些参考资料:
- https://trac.edgewall.org/ticket/12046
io.StringIO 需要一个 unicode 字符串。io.BytesIO 需要一个字节字符串。StringIO.StringIO 允许 unicode 或字节字符串。cStringIO.StringIO 需要一个被编码为字节字符串的字符串。
但cStringIO.StringIO('abc')
不会引发任何错误。
https://review.openstack.org/#/c/286926/1
StringIO 类是错误的类,特别是考虑到子单元 v2 是二进制而不是字符串。
http://comments.gmane.org/gmane.comp.python.devel/148717
cStringIO.StringIO(b'data') 没有复制数据,而 io.BytesIO(b'data') 进行复制(即使以后没有修改数据)。
2014 年的这篇文章中有一个修复补丁。
- 此处未列出许多 SO 帖子。
这是 Eric 示例的 Python 2.7 结果
%timeit cStringIO.StringIO(u_data)
1000000 loops, best of 3: 488 ns per loop
%timeit cStringIO.StringIO(b_data)
1000000 loops, best of 3: 448 ns per loop
%timeit StringIO.StringIO(u_data)
1000000 loops, best of 3: 1.15 µs per loop
%timeit StringIO.StringIO(b_data)
1000000 loops, best of 3: 1.19 µs per loop
%timeit io.StringIO(u_data)
1000 loops, best of 3: 304 µs per loop
# %timeit io.StringIO(b_data)
# error
# %timeit io.BytesIO(u_data)
# error
%timeit io.BytesIO(b_data)
10000 loops, best of 3: 77.5 µs per loop
至于 2.7,cStringIO.StringIO
并且StringIO.StringIO
比io
.