mypy 声明 IO[bytes] 与 BinaryIO 不兼容

jwo*_*der 9 python type-hinting mypy

考虑以下代码:

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()
Run Code Online (Sandbox Code Playgroud)

在 Python 3.6.9 下在上述代码上运行 mypy v0.782 失败并出现以下错误:

zfopen.py:8: error: Argument 1 to "TextIOWrapper" has incompatible type "IO[bytes]"; expected "BinaryIO"
Run Code Online (Sandbox Code Playgroud)

但是,我觉得这段代码不应该被视为错误,因为ZipFile.open()返回了一个TextIOWrapper接受的二进制文件句柄。此外,IO[bytes]BinaryIO(据我所知)实际上是一回事;它只是BinaryIO被声明为IO[bytes]. 我天真地希望IO[bytes]在任何地方都能被接受BinaryIO,除了这不是子类的工作方式,而且我不确定在打字时如何正确利用这个子类。

谁在这里出错了,如何修复错误?

  • 声明返回类型ZipFile.open()asIO[bytes]而不是typeshed 是否错误BinaryIO
  • 将第一个参数的类型声明为TextIOWrapperasBinaryIO而不是IO[bytes]
  • typing模块是否在创建BinaryIO子类IO[bytes]而不是别名时出错?
  • 我的代码是否因为没有执行某种类型的转换而出错bfp
  • 我的想法是否错误地期望bfp可以通过TextIOWrapper未修改?

Jer*_*101 5

这个带有 mypy 0.782 的较短测试用例得到相同的错误:

    binary_file = io.open('foo.bin', 'rb')
    text_file = io.TextIOWrapper(binary_file, encoding='utf-8', newline='')
Run Code Online (Sandbox Code Playgroud)

是否binary_file明确声明为IO[bytes]或推断。

修复:使用mypy 0.770mypy 0.790

这是 mypy 排版(问题 4349)中的一个回归,修复在 mypy 0.790 中,修复了zipfile.open()io.open().