如何符合 mypy 类型 'SupportsWrite[str]'?
How does one comply with the mypy type 'SupportsWrite[str]'?
我有一个 'smart' 打开各种文件的函数和 returns 一个 IO-ish 对象类型:
def sopen(anything_at_all: str, mode: str) -> FileIO:
...
我在打印语句中使用它,例如:
with sopen('footxt.gz', mode = 'w+') as fout:
print("hello, world!", file=fout)
然后,当用mypy
0.812分析这段代码时,我得到以下神秘错误:
Argument "fout" to "print" has incompatible type "FileIO"; expected "Optional[SupportsWrite[str]]"
很好:SupportsWrite
肯定比 FileIO
好,只有一个问题:当我调整我的代码以支持使用 [=20= 写入时,没有比 FileIO
更好的了...
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
的意愿?
TL;DR 使用 typing.IO
而不是 FileIO
。 typing.IO
支持内置 open
可能 return.
的所有 return 类型
print
本身将其 file
参数注释为 Optional[SupportsWrite[str]]
,因此 mypy
是正确的。
要修复缺少的 _typeshed
模块错误(也是正确的,它仅在类型检查时可用,而不是在解释器执行代码时可用)您可以使用 if TYPE_CHECKING
1 技巧,然后使用字符串注释。
下面几乎满足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)
将此提供给 mypy
结果
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
的 return 类型)而不是直接弄乱 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)
1 TYPE_CHECKING
是一个常量,默认为 False
,并且仅由 [=20= 设置为 True
] and/or 其他类型的分析工具。
我有一个 'smart' 打开各种文件的函数和 returns 一个 IO-ish 对象类型:
def sopen(anything_at_all: str, mode: str) -> FileIO:
...
我在打印语句中使用它,例如:
with sopen('footxt.gz', mode = 'w+') as fout:
print("hello, world!", file=fout)
然后,当用mypy
0.812分析这段代码时,我得到以下神秘错误:
Argument "fout" to "print" has incompatible type "FileIO"; expected "Optional[SupportsWrite[str]]"
很好:SupportsWrite
肯定比 FileIO
好,只有一个问题:当我调整我的代码以支持使用 [=20= 写入时,没有比 FileIO
更好的了...
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
的意愿?
TL;DR 使用 typing.IO
而不是 FileIO
。 typing.IO
支持内置 open
可能 return.
print
本身将其 file
参数注释为 Optional[SupportsWrite[str]]
,因此 mypy
是正确的。
要修复缺少的 _typeshed
模块错误(也是正确的,它仅在类型检查时可用,而不是在解释器执行代码时可用)您可以使用 if TYPE_CHECKING
1 技巧,然后使用字符串注释。
下面几乎满足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)
将此提供给 mypy
结果
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
的 return 类型)而不是直接弄乱 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)
1 TYPE_CHECKING
是一个常量,默认为 False
,并且仅由 [=20= 设置为 True
] and/or 其他类型的分析工具。