我一辈子都无法让MyPy查找未与源代码共存的 stub 。这是我的项目结构:
trymypy/
|- stubs/
| \- foo.pyi
|- __init__.py
|- usefoo.py
\- foo.py
# foo.py
def foofunc(x):
return str(x)
# usefoo.py
from trymypy.foo import foofunc
print(foofunc(5) + 5)
# stubs/foo.pyi
def foofunc(x: int) -> str: ...
我已经将
MYPYPATH
环境变量设置为/full/path/to/trymypy/stubs
,以便MyPy应该在stubs
目录中查找我的.pyi
文件。这不应通过类型检查。 MyPy应该这样标记错误:
../trymypy/usefoo.py:3: error: Unsupported operand types for + ("str" and "int")
而是,MyPy不会标记任何错误,因为它没有读取 stub 文件。如果我将 stub 文件
foo.pyi
移到与foo.py
并置的目录的根项目中,它将正确标记,这向我指示MYPYPATH
未被拾取或未正确定义。我也尝试在配置文件
mypy_path
中设置mypy.ini
:[mypy]
python_version = 3.7
mypy_path = /full/path/to/trymypy/stubs
确实会收到
mypy.ini
中的其他配置选项(例如python_version
),因此MyPy正在查看文件并正在读取文件。完全被困在这里。这是一个(非常)简单的示例,似乎它应该按照MyPy的说明工作。我已经用尽变量以进行试验。
我正在使用Python 3.7,并且在仅安装了mypy的虚拟环境中工作。
最佳答案
长话短说:您可能希望将foo.pyi
文件与trymypy
一起移到顶层foo.py
文件夹中,而不是使用一个单独的“stubs”目录。
长话短说,目前您的设置存在两个问题。
第一个问题是 stub 的文件夹结构需要反射(reflect)基础代码的结构方式。因此,由于要执行from trymypy.foo import blah
,因此需要将文件夹结构调整为如下所示:
trymypy/
|- stubs/
| |- trymypy/
| | |- __init__.pyi
| \ \- foo.pyi
|- __init__.py
|- usefoo.py
\- foo.py
您应该继续将mypypath设置为指向
trymypy/stubs
。您可以使用绝对路径或相对路径。更大的第二个问题是,取决于您对mypy的调用方式,您的 stub 最终可能会被遮蔽并被忽略。例如,如果您从
mypy -p trymypy
文件夹外部运行trymypy
,mypy将首先解析每个trymypy
及其直接包含的两个子模块(trymypy.__init__
,trymypy.usefoo
和trymypy.foo
)。而且,一旦加载了
trymypy.foo
,mypy便不会再尝试重新加载它,这意味着它永远不会打扰检查您指定的 stub 。但是,如果您尝试对单个文件(例如
mypy -m trymypy.usefoo
,mypy -p trymypy.usefoo
)进行类型检查,则mypy不会尝试将所有内容加载到trymypy
中,这意味着它可以使用典型的import resolution rules找到 stub 。您可以通过传递
-v
标志来确认所有这些行为,该标志以冗长模式运行mypy并准确打印出要加载的内容。每次运行前,请确保删除.mypy_cache
目录。注意:实际上,我真的不知道这种行为差异是故意的还是mypy中的错误。导入规则非常细微。
幸运的是,此修复非常简单:只需将
foo.pyi
文件移动到顶级trymypy
文件夹中,如下所示:trymypy/
|- __init__.py
|- usefoo.py
|- foo.py
\- foo.pyi
现在,无论以什么顺序导入什么内容,由于两个文件都位于同一目录中,因此mypy始终会同时找到
foo.py
和foo.pyi
。并且,每当py
和pyi
文件位于同一目录中时,pyi
文件始终会获胜(而py文件将被忽略)。关于这个新的文件夹结构,您可能有两个后续问题:
foo.py
中存在的类型提示来对foo.pyi
的内容进行类型检查?答案是否定的,目前没有办法。如果存在
foo.pyi
,则mypy会完全忽略foo.py
的正文。尽管有人对adding support for this feature感兴趣,所以您也许可以订阅链接的Github问题进行更新。 答案是,当您要为第三方库添加 stub 时,它主要有用。我实际上对“为您自己的代码添加 stub ”工作流程没有很多经验,但是我的理解是,通常以上述方式“内联”此类 stub 。
关于python - 如何正确设置MYPYPATH来为mypy拾取 stub ?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55437746/