如何正确设置MYPYPATH来为mypy拾取存根?

时间:2019-03-31 03:58:29

标签: python python-3.x mypy

我无法终生让MyPy查找与源代码不在同一位置的存根。这是我的项目结构:

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不会标记任何错误,因为它没有读取存根文件。如果我将存根文件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的虚拟环境中工作。

1 个答案:

答案 0 :(得分:1)

长话短说:您可能希望将foo.pyi文件移到顶层trymypy文件夹中,与foo.py并排,而不是使用一个单独的'stubs'目录。


长话短说,目前您的设置存在两个问题。

第一个问题是存根的文件夹结构需要反映基础代码的结构方式。因此,由于您想进行from trymypy.foo import blah,因此需要调整文件夹结构,使其看起来像这样:

trymypy/
|- stubs/
|  |- trymypy/
|  |  |- __init__.pyi
|  \  \- foo.pyi
|- __init__.py
|- usefoo.py
\- foo.py

您应继续将mypypath设置为指向trymypy/stubs。您可以使用绝对路径或相对路径。

更大的第二个问题是您的存根最终可能会被隐藏和忽略,具体取决于您调用mypy的方式。例如,如果您从mypy -p trymypy文件夹外部运行trymypy,则mypy将首先解析每个trymypy及其直接包含的两个子模块(trymypy.__init__,{{1 }}和trymypy.usefoo)。

一旦加载trymypy.foo,mypy就不会再尝试重新加载它,这意味着它永远不会打扰检查您指定的存根。

但是,如果您尝试对单个文件(例如trymypy.foomypy -m trymypy.usefoo)进行类型检查,则mypy不会尝试将所有内容加载到mypy -p trymypy.usefoo中,这意味着它可以使用以下命令找到存根典型的import resolution rules

您可以通过传递trymypy标志来确认所有这些行为,该标志在详细模式下运行mypy并准确打印出加载的内容。每次运行前,请确保删除-v目录。

注意:实际上,我实际上不知道这种行为差异是故意的还是mypy中的错误。导入规则非常细微。


不过,修复非常简单:只需将.mypy_cache文件移动到顶级foo.pyi文件夹中,如下所示:

trymypy

现在,无论以什么顺序导入什么内容,由于两个文件都位于同一目录中,因此mypy将始终同时找到trymypy/ |- __init__.py |- usefoo.py |- foo.py \- foo.pyi foo.py。每当foo.pyipy文件位于同一目录中时,pyi文件总是会胜出(并且py文件将被忽略)。


关于此新文件夹结构,您可能有两个后续问题:

  1. 是否可以使用pyi中存在的类型提示来对foo.py的内容进行类型检查?

    答案是否定的,目前没有办法。如果您有foo.pyi,则foo.pyi的主体实际上会被mypy完全忽略。不过,有些人对adding support for this feature感兴趣,因此您也许可以订阅链接的Github问题进行更新。

  2. 创建一个单独的“存根”文件夹最终在这里没有用。那么 有用吗?

    答案是,当您要为第三方库添加存根时,它主要有用。我实际上对“为您自己的代码添加存根”工作流程没有很多经验,但是我的理解是,通常以上述方式“内联”此类存根。