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从技术上讲,它能解决问题(从错误消失的意义上讲),但它的工作速度比unbuffered
gzip.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'