Python io.BufferedReader是否真正支持readline?
根据Python io.BufferedReader是否真正支持readline?,python,io,python-3.6,Python,Io,Python 3.6,根据io.BufferedReader继承io.IOBase:io.IOBase->io.BufferedReader->io.BufferedReader。因此,它应该实现readline和readinto,但事实似乎并非如此,因为我得到了一个AttributeError。一个简单的例子: 数据样本: $ printf 'foo bar\nspam ham\n' | gzip -c > compressed_file.gz 测试代码: import gzip import io wi
io.BufferedReader
继承io.IOBase
:io.IOBase
->io.BufferedReader
->io.BufferedReader
。因此,它应该实现readline
和readinto
,但事实似乎并非如此,因为我得到了一个AttributeError
。一个简单的例子:
数据样本:
$ printf 'foo bar\nspam ham\n' | gzip -c > compressed_file.gz
测试代码:
import gzip
import io
with io.BufferedReader(gzip.open('compressed_file.gz', 'rt')) as buffer:
buffer.readline()
例外情况:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-2-215a0d9b4feb> in <module>()
3
4 with io.BufferedReader(gzip.open('compressed_file.gz', 'rt')) as buffer:
----> 5 buffer.readline()
AttributeError: '_io.TextIOWrapper' object has no attribute 'readinto'
似乎是
\u io.TextIOWrapper
由io.BufferedReader
返回的实例与io.TextIOWrapper
实例不同,尽管后者是后者。是的,您确实缺少一个关键细节:围绕现有对象的包装:
类io.BufferedReader(原始,缓冲区大小=默认缓冲区大小)
一种缓冲区,提供对可读的、顺序的RawIOBase
对象的高级访问
而且,由于您已在text模式下打开了gzip文件,因此它不是RawIOBase
实例:
>>> f = gzip.open('compressed_file.gz', 'rt')
>>> isinstance(f, io.RawIOBase)
False
换句话说,这是一个用户错误
如果将BufferedReader
包装在二进制文件中,您将看到readline
方法工作正常:
>>> io.BufferedReader(io.BytesIO(b'foo\nbar')).readline()
b'foo\n'
为什么选择以文本模式打开<代码>[t]->text,
b->
binary@MosesKoledoye因为我正在将句柄传递给第三方函数,它需要一个TextIO实例。更新部分中的代码现在能解决您的问题吗?@JanneKarila从技术上讲,它能解决问题(从错误消失的意义上讲),但它的工作速度比unbufferedgzip.open慢(…,'rt')
。在Python2中,缓冲解决方案曾经很好地解决了Python执行速度极慢的gzip
的问题,但仅此而已。为什么要投反对票?问题是,没有BufferedReader
包装器,整个过程都可以正常运行。也就是gzip.open(…,'rt'))
返回一个带有正确实现的读线的句柄。因此,如果BufferedReader
应该返回底层缓冲区周围的包装,那么这不是用户错误。顺便说一句:io.TextIOWrapper
继承io.TextIOBase
,后者反过来继承io.IOBase
(定义readline
和readinto
的基类)问题似乎是BufferedReader
返回的\u io.TextIOWrapper
与io.TextIOWrapper
不同,尽管io
模块直接从C扩展\u io
导入TextIOWrapper
。
>>> io.BufferedReader(io.BytesIO(b'foo\nbar')).readline()
b'foo\n'