Why isn't this function type-annotated correctly (error: Missing type parameters for generic type)?
Why isn't this function type-annotated correctly (error: Missing type parameters for generic type)?
这个函数的类型注释是否正确?
import subprocess
from os import PathLike
from typing import Union, Sequence, Any
def run(shell_command: Union[bytes, str, Sequence[Union[bytes, str, PathLike]]], **subprocess_run_kwargs: Any) -> int:
return subprocess.run(shell_command, check=True, shell=True, **subprocess_run_kwargs).returncode
我猜不是,因为我得到:
he\other.py:6: error: Missing type parameters for generic type
得到同样的错误,然后把上面的代码保存在other.py
,然后:
$ pip install mypy
$ mypy --strict other.py
PathLike
是泛型类型,所以需要和类型参数一起使用(例如AnyStr
):
import subprocess
from os import PathLike
from typing import Union, Sequence, Any, AnyStr
def run(shell_command: Union[bytes, str, Sequence[Union[bytes, str, PathLike[AnyStr]]]], **subprocess_run_kwargs: Any) -> int:
return subprocess.run(shell_command, check=True, shell=True, **subprocess_run_kwargs).returncode
相关问题:
更新
抱歉,我没有在运行时检查这段代码。通过一些技巧,可以编写一个解决方法:
import subprocess
from os import PathLike as BasePathLike
from typing import Union, Sequence, Any, AnyStr, TYPE_CHECKING
import abc
if TYPE_CHECKING:
PathLike = BasePathLike
else:
class FakeGenericMeta(abc.ABCMeta):
def __getitem__(self, item):
return self
class PathLike(BasePathLike, metaclass=FakeGenericMeta):
pass
def run(shell_command: Union[bytes, str, Sequence[Union[bytes, str, PathLike[AnyStr]]]], **subprocess_run_kwargs: Any) -> int:
return subprocess.run(shell_command, check=True, shell=True, **subprocess_run_kwargs).returncode
与此解决方法相关的问题:
- mypy: how to define a generic subclass
- https://github.com/python/mypy/issues/5264
如 sanyash 的回答所述,os.PathLike
被定义为泛型。你可以看看stub in the typeshed repo。但是,os.PathLike
仅在存根文件中是通用的,可从 os
导入的实现不是 .
未指定类型 var 参数 (path: PathLike
) 会导致 mypy 错误。指定类型 var 参数 (path: PathLike[Any]
) 会导致 Python 解释器(运行时)错误。
由于 #5667. As a result PR #5833 扩展了 mypy 文档,因此在 mypy 存储库中提出了这个确切的问题:
添加的部分指出了三种处理方法:
可以通过特殊的 from __future__ import annotations
导入 see here 禁用 Python 解释器(在运行时)对注解的解释。这计划成为 Python 3.10 中的默认设置,并解决了一堆与注释相关的问题。
from __future__ import annotations
from os import PathLike
import subprocess
from typing import Any, Sequence, Union
def run(shell_command: Union[bytes, str, Sequence[Union[bytes, str, PathLike[Any]]]], **subprocess_run_kwargs: Any) -> int:
return subprocess.run(shell_command, check=True, shell=True, **subprocess_run_kwargs).returncode
根据类型检查器或 Python 解释器(运行时)解释文件,使用 typing.TYPE_CHECKING
提供不同的注释。
from os import PathLike
import subprocess
from typing import Any, Sequence, TYPE_CHECKING, Union
if TYPE_CHECKING:
BasePathLike = PathLike[Any]
else:
BasePathLike = PathLike
def run(shell_command: Union[bytes, str, Sequence[Union[bytes, str, BasePathLike]]], **subprocess_run_kwargs: Any) -> int:
return subprocess.run(shell_command, check=True, shell=True, **subprocess_run_kwargs).returncode
以字符串形式提供注释。 Python 解释器(运行时)不会解释注释,但 mypy 会获取正确的含义。
import subprocess
from typing import Any, Sequence, Union
def run(shell_command: Union[bytes, str, Sequence[Union[bytes, str, 'PathLike[Any]']]], **subprocess_run_kwargs: Any) -> int:
return subprocess.run(shell_command, check=True, shell=True, **subprocess_run_kwargs).returncode
这个函数的类型注释是否正确?
import subprocess
from os import PathLike
from typing import Union, Sequence, Any
def run(shell_command: Union[bytes, str, Sequence[Union[bytes, str, PathLike]]], **subprocess_run_kwargs: Any) -> int:
return subprocess.run(shell_command, check=True, shell=True, **subprocess_run_kwargs).returncode
我猜不是,因为我得到:
he\other.py:6: error: Missing type parameters for generic type
得到同样的错误,然后把上面的代码保存在other.py
,然后:
$ pip install mypy
$ mypy --strict other.py
PathLike
是泛型类型,所以需要和类型参数一起使用(例如AnyStr
):
import subprocess
from os import PathLike
from typing import Union, Sequence, Any, AnyStr
def run(shell_command: Union[bytes, str, Sequence[Union[bytes, str, PathLike[AnyStr]]]], **subprocess_run_kwargs: Any) -> int:
return subprocess.run(shell_command, check=True, shell=True, **subprocess_run_kwargs).returncode
相关问题:
更新
抱歉,我没有在运行时检查这段代码。通过一些技巧,可以编写一个解决方法:
import subprocess
from os import PathLike as BasePathLike
from typing import Union, Sequence, Any, AnyStr, TYPE_CHECKING
import abc
if TYPE_CHECKING:
PathLike = BasePathLike
else:
class FakeGenericMeta(abc.ABCMeta):
def __getitem__(self, item):
return self
class PathLike(BasePathLike, metaclass=FakeGenericMeta):
pass
def run(shell_command: Union[bytes, str, Sequence[Union[bytes, str, PathLike[AnyStr]]]], **subprocess_run_kwargs: Any) -> int:
return subprocess.run(shell_command, check=True, shell=True, **subprocess_run_kwargs).returncode
与此解决方法相关的问题:
- mypy: how to define a generic subclass
- https://github.com/python/mypy/issues/5264
如 sanyash 的回答所述,os.PathLike
被定义为泛型。你可以看看stub in the typeshed repo。但是,os.PathLike
仅在存根文件中是通用的,可从 os
导入的实现不是 .
未指定类型 var 参数 (path: PathLike
) 会导致 mypy 错误。指定类型 var 参数 (path: PathLike[Any]
) 会导致 Python 解释器(运行时)错误。
由于 #5667. As a result PR #5833 扩展了 mypy 文档,因此在 mypy 存储库中提出了这个确切的问题:
添加的部分指出了三种处理方法:
可以通过特殊的
from __future__ import annotations
导入 see here 禁用 Python 解释器(在运行时)对注解的解释。这计划成为 Python 3.10 中的默认设置,并解决了一堆与注释相关的问题。from __future__ import annotations from os import PathLike import subprocess from typing import Any, Sequence, Union def run(shell_command: Union[bytes, str, Sequence[Union[bytes, str, PathLike[Any]]]], **subprocess_run_kwargs: Any) -> int: return subprocess.run(shell_command, check=True, shell=True, **subprocess_run_kwargs).returncode
根据类型检查器或 Python 解释器(运行时)解释文件,使用
typing.TYPE_CHECKING
提供不同的注释。from os import PathLike import subprocess from typing import Any, Sequence, TYPE_CHECKING, Union if TYPE_CHECKING: BasePathLike = PathLike[Any] else: BasePathLike = PathLike def run(shell_command: Union[bytes, str, Sequence[Union[bytes, str, BasePathLike]]], **subprocess_run_kwargs: Any) -> int: return subprocess.run(shell_command, check=True, shell=True, **subprocess_run_kwargs).returncode
以字符串形式提供注释。 Python 解释器(运行时)不会解释注释,但 mypy 会获取正确的含义。
import subprocess from typing import Any, Sequence, Union def run(shell_command: Union[bytes, str, Sequence[Union[bytes, str, 'PathLike[Any]']]], **subprocess_run_kwargs: Any) -> int: return subprocess.run(shell_command, check=True, shell=True, **subprocess_run_kwargs).returncode