为什么Mypy抱怨TextIOWrapper接收GzipFile作为参数1?

问题描述 投票:1回答:1

我正在将内容写入内存中的二进制流,以便将内容上载到S3而不将其存储在本地文件中(我的内存比磁盘空间大)。以下代码有效,但mypy mvce.py失败,并带有

mvce.py:6: error: Argument 1 to "TextIOWrapper" has incompatible type "GzipFile";
expected "IO[bytes]"
Found 1 error in 1 file (checked 1 source file)

mvce.py

from io import BytesIO, TextIOWrapper
import gzip

inmem = BytesIO()
with gzip.GzipFile(fileobj=inmem, mode="wb") as gzip_handler, TextIOWrapper(
    gzip_handler, encoding="utf-8"
) as wrapper:
    wrapper.write("some test string")


# Check if this actually worked
with open("foobar.gzip", "wb") as f1:
    inmem.seek(0)
    f1.write(inmem.read())


with gzip.open("foobar.gzip", "rb") as f2:
    data = f2.read()

print(data)

问题

为什么mypy失败,如何使它工作?有潜在的潜在问题吗?

python-3.x mypy
1个回答
1
投票

为什么MyPy失败?

MyPy使用一组称为Typeshed的类型存根来定义标准库的类型。在Typeshed中,gzip.GzipFile不继承自typing.IO[bytes]

类层次结构是:gzip.GzipFile -> _compression.BaseStream -> io.BufferedIOBase -> io.IOBase

我如何使其起作用?

您可以使用typing.cast(IO[bytes], gzip_handler)向MyPy暗示GzipFile实例应被视为二进制文件对象。有关演员表的更多信息,请参见documentation

或者,您可以使用gzip.open(inmem, mode='wt', encoding="utf-8")直接获取文本文件对象(基本上与您所做的相同,请参见下文)。此函数在Typeshed中具有返回类型IO[Any]

是否存在潜在的潜在问题?

gzip documentation关于gzip功能的说明:

对于文本模式,将创建一个gzip.open()对象,并使用指定的编码,错误处理行为和行尾将其包装在GzipFile实例中。

所以您的代码在实践中应该可以正常工作。

可以在排版中解决此问题吗?

我尝试在Typeshed中将GzipFile添加为io.TextIOWrapper的超类,但在测试中出现一个错误:

io.TextIOWrapper

此问题的解决方案留给读者练习。

© www.soinside.com 2019 - 2024. All rights reserved.