为什么不能正确注释该函数的类型(错误:通用类型的类型参数丢失)?

时间:2019-03-09 11:17:23

标签: python python-3.x mypy

此函数的类型标注正确吗?

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

2 个答案:

答案 0 :(得分:1)

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

与此变通办法相关的问题:

答案 1 :(得分:1)

如sanyash的答案所述,os.PathLike被定义为通用类型。您可以查看stub in the typeshed repo。但是,os.PathLike仅在存根文件中是通用的,os导入的实现不是

不指定类型var参数(path: PathLike)会导致mypy错误。指定类型var参数(path: PathLike[Any])会导致Python解释器(运行时)错误。

在mypy仓库中已提出此确切问题{​​{3}}。结果,#5667扩展了mypy文档:

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

  1. 使用typing.TYPE_CHECKING提供不同的注释,具体取决于类型检查器还是Python解释器(运行时)来解释文件。

    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
    
  2. 将注释作为字符串提供。 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
    
相关问题