考虑以下代码:
from io import TextIOWrapper
from typing import List
from zipfile import ZipFile
def read_zip_lines(zippath: str, filename: str) -> List[str]:
with ZipFile(zippath) as zf:
with zf.open(filename) as bfp:
with TextIOWrapper(bfp, 'utf-8') as fp:
return fp.readlines()
在 Python 3.6.9 下对上述代码运行 mypy v0.782 失败,并出现以下错误:
zfopen.py:8: error: Argument 1 to "TextIOWrapper" has incompatible type "IO[bytes]"; expected "BinaryIO"
但是,我觉得这段代码不应该被视为错误,因为
ZipFile.open()
返回一个二进制文件句柄,TextIOWrapper
接受它。 此外, IO[bytes]
和 BinaryIO
(据我所知)实际上是同一件事;只是 BinaryIO
被声明为 IO[bytes]
的子类。 我天真地期望 IO[bytes]
在 BinaryIO
所在的任何地方都被接受,除了这不是子类的工作方式,而且我不确定在打字时如何正确使用这个子类。
谁错了,如何修复错误?
ZipFile.open()
的返回类型声明为 IO[bytes]
而不是 BinaryIO
是否输入错误?TextIOWrapper
的第一个参数的类型声明为 BinaryIO
而不是 IO[bytes]
是否存在打字错误?typing
模块是否错误地使BinaryIO
成为IO[bytes]
的子类而不是别名?bfp
执行某种类型的转换而出错?bfp
可以通过 TextIOWrapper
未经修改?这个较短的 mypy 0.782 测试用例得到了相同的错误:
binary_file = io.open('foo.bin', 'rb')
text_file = io.TextIOWrapper(binary_file, encoding='utf-8', newline='')
binary_file
是否显式声明为IO[bytes]
或推断。
修复:使用
mypy 0.770
或mypy 0.790
。
这是 mypy 的 typeshed 中的回归(Issue 4349),修复在 mypy 0.790 中,修复了
zipfile.open()
和 io.open()
。