为什么 mypy 认为缺少库导入?

Sal*_*ley 23 python mypy

当我运行 mypy 时,它抱怨找不到模块:

sal@ahfang:~/workspace/ecs/cx-project-skeleton-repo/src/cx-example-function$ pipenv run python -m mypy .
example_lambda.py:3: error: Cannot find module named 'aws_xray_sdk.core'
Run Code Online (Sandbox Code Playgroud)

但是当尝试使用完全相同的 Python 解释器导入完全相同的模块时,似乎该模块确实存在并且是可导入的。

python 
Python 3.7.3 (default, Apr  3 2019, 05:39:12) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import aws_xray_sdk.core
>>>
Run Code Online (Sandbox Code Playgroud)

除了强制忽略 mypy.ini 文件中的导入之外,我还应该做些什么来帮助 mypy 查看确实存在的可导入模块?

boo*_*dev 26

有时,它可能就像__init__.py在包中添加文件一样简单。

我遇到了同样的问题,并意识到我尝试导入的包丢失了该__init__.py文件。因此 mypy 无法“看到”导入。

  • 我在“tests/”文件夹中丢失了“__init__.py”。这解决了它 (5认同)
  • 如果您不希望到处都有“__init__.py”,还有“mypy”的“--namespace-packages”选项。 (2认同)

Mic*_*x2a 15

所以,这里的问题的症结所在:mypy并没有尝试的类型检查已经导入的每一个模块。相反,它只尝试对明确选择加入类型生态系统的模块进行类型检查。

模块可以通过两个关键机制选择加入类型生态系统:

  1. 将类型提示或存根添加到他们的代码中,并py.typed在他们分发给 PyPi(或任何其他包存储库)的包中包含一个命名的文件。这个标记的存在使得包PEP-561-aware。mypy 文档还有更多关于PEP-561-aware 包的信息
  2. 或者,将存根添加到typeshed,标准库的类型提示存储库并选择 3rd 方库。

aws_xray_sdk包已完成没有这些东西,所以会被mypy被忽略。


这有点不幸,所以你能做什么?mypy 文档的缺少导入部分有一些关于如何操作的详细建议,但总而言之,您基本上有三个选项,我将按从最少到最多的顺序列出:

  1. 只需通过手动# type: ignore为每个导入添加注释来使导入静音。您还可以将以下部分添加到 mypy 配置文件中以自动执行此操作:

    [mypy-aws_xray_sdk]
    ignore_missing_imports = True
    
    Run Code Online (Sandbox Code Playgroud)

    现在,您从此模块导入的任何内容都将被视为类型Any

  2. 四处搜索,看看是否有人为您的库创建了第三方存根包:基本上,一个非官方(或有时是半官方)PEP-561 感知包,包含类型提示。例如,对于 django,有django-stubs,对于 SqlAlchemy,有 sqlalchemy -stubs

  3. 为此库创建您自己的存根,并通过mypy_pathmypy 配置文件中的选项指向它们:

    mypy_path = my_stubs/aws_xray_sdk, my_stubs/some_other_library
    
    Run Code Online (Sandbox Code Playgroud)

    这些存根不必是完整的,不一定是:您只需为您正在使用的少数内容添加注释即可。(如果它们最终变得相对完整,您可能会考虑将它们贡献回开源社区。)


最后,您可能想知道为什么mypy 会这样?

部分原因是因为在一般情况下,mypy 仅尝试查找和分析模块是不安全的。只是盲目地导入和使用未准备好类型提示的包有时会导致奇怪的类型错误,或者更糟糕的是,可能会导致代码被错误地标记为类型安全。也就是说,如果您关心类型安全,最好立即通知您正在使用的某些包没有类型提示,而不是 mypyAny在您的代码中盲目推断和涂抹s。

不过,至少在大多数情况下,Mypy可以在此处提供更好的错误消息。IMO 事实并非如此,这在很大程度上是一种疏忽。在https://github.com/python/mypy/issues/4542 中有一些关于这个的讨论。

  • 您还可以使用“--ignore-missing-imports”标志运行 mypy (12认同)

val*_*lex 8

作为@Michael0x2a 答案的补充。有一个选项可以忽略所有导入中的这些错误mypy.ini

[mypy]
ignore_missing_imports = True
Run Code Online (Sandbox Code Playgroud)