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

与此解决方法相关的问题:

如 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 存储库中提出了这个确切的问题:

添加的部分指出了三种处理方法:

  1. 可以通过特殊的 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
    
  2. 根据类型检查器或 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
    
  3. 以字符串形式提供注释。 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