如何符合mypy类型“SupportsWrite[str]”的要求?

2024-05-14 03:29:44 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个“智能”打开函数,可以打开各种文件并返回IO-ish对象类型:

def sopen(anything_at_all: str, mode: str) -> FileIO:
   ...

我在打印语句中使用它,如:

with sopen('footxt.gz', mode = 'w+') as fout:
    print("hello, world!", file=fout)

然后,当使用mypy0.812分析此代码时,我得到以下神秘错误:

Argument "fout" to "print" has incompatible type "FileIO"; expected "Optional[SupportsWrite[str]]"

好的,很好:SupportsWrite肯定比FileIO好,只有一个问题:当我调整代码以支持使用_typeshed.SupportsWrite写时,没有什么比这更好了

def sopen(anything_at_all: str, mode: str) \
  -> Union[SupportsWrite[str],SupportsRead[str]]:
  ...

mypy想要确切地说Optional[SupportsWrite]

 Argument "fout" to "print" has incompatible type "Union[SupportsWrite[str], SupportsRead[str]]"; expected "Optional[SupportsWrite[str]]"

接下来,我尝试铸造,并创建某种类型的强制强制执行,但是在解释器中试用我的脚轮的过程中,当

>>> from _typeshed import SupportsRead, SupportsWrite
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named '_typeshed'

现在的根本问题是:在这种情况下,人们如何遵从mypy的意愿


Tags: 类型modedefalloptionalatfileioprint
1条回答
网友
1楼 · 发布于 2024-05-14 03:29:44

TL;DR使用typing.IO代替FileIOtyping.IO支持内置open可能返回的所有返回类型


print本身将其file参数注释为Optional[SupportsWrite[str]],因此mypy是正确的

要修复丢失的_typeshed模块错误(同样正确,它仅在类型检查时可用,而在解释器执行代码时不可用),可以使用if TYPE_CHECKING1技巧,然后使用字符串注释

下面的几乎满足mypy

from typing import Optional, TYPE_CHECKING

if TYPE_CHECKING:
    from _typeshed import SupportsWrite

def sopen(anything_at_all: str, mode: str) -> 'Optional[SupportsWrite[str]]':
   ...

with sopen('footxt.gz', mode = 'w+') as fout:
    print("hello, world!", file=fout)

test.py:9: error: Item "SupportsWrite[str]" of "Optional[SupportsWrite[str]]" has no attribute "__enter__"
test.py:9: error: Item "None" of "Optional[SupportsWrite[str]]" has no attribute "__enter__"
test.py:9: error: Item "SupportsWrite[str]" of "Optional[SupportsWrite[str]]" has no attribute "__exit__"
test.py:9: error: Item "None" of "Optional[SupportsWrite[str]]" has no attribute "__exit__"

输入typing.IO

您可以简单地使用typing.IO(这也恰好与open的返回类型匹配),而不是直接处理SupportsWrite。以下内容完全满足mypy

from typing import IO

def sopen(anything_at_all: str, mode: str) -> IO:
   ...

with sopen('footxt.gz', mode = 'w+') as fout:
    print("hello, world!", file=fout)

1TYPE_CHECKING是一个常量,默认情况下为False,并且仅由mypy和/或其他类型分析工具设置为True

相关问题 更多 >