当我运行 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'
但是当尝试使用完全相同的 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
>>>
除了强制忽略 mypy.ini 文件中的导入之外,我应该做些什么来帮助 mypy 查看确实存在的可导入模块?
原文由 Salim Fadhley 发布,翻译遵循 CC BY-SA 4.0 许可协议
所以,这就是问题的症结所在:mypy 不会 尝试对您导入的每个模块进行类型检查。相反,它只尝试对已明确选择加入打字生态系统的模块进行类型检查。
模块可以通过两个关键机制选择加入打字生态系统:
py.typed
的文件。这个标记的存在使得包 PEP-561-aware 。 mypy 文档也有更多关于 PEP-561-aware packages 的 信息。aws_xray_sdk
包没有做这些事情,所以将被 mypy 忽略。这有点不幸,所以你能做什么? mypy 文档的 Missing imports 部分有一些关于该做什么的详细建议,但总而言之,您基本上有三个选项,我将按照从最少到最多的努力的顺序列出:
# type: ignore
注释到每个导入来使导入静音。您还可以将以下部分添加到您的 mypy 配置文件中以自动执行此操作:现在,您从该模块导入的任何内容都将被视为类型
Any
。搜索并查看是否有人为您的库创建了 第三方 存根包:基本上,一个非官方(或有时是半官方)感知 PEP-561 的包, 仅 包含类型提示。例如,对于 django,有 django-stubs ,对于 SqlAlchemy,有 sqlalchemy -stubs 。
为此库创建您自己的存根,并通过 mypy 配置文件中的
mypy_path
选项指向它们:这些存根不一定是完整的:您只需为正在使用的少数东西添加注释即可。 (如果它们最终变得相对完整,您或许可以考虑将它们贡献回开源社区。)
最后,您可能想知道 为什么 mypy 会这样?
部分原因是因为在一般情况下 mypy 仅尝试查找和分析模块是不安全的。只是盲目地导入和使用未准备好类型提示的包有时会导致奇怪的类型错误,或者更糟的是,可能导致代码被错误地标记为类型安全。也就是说,如果您关心类型安全,最好立即通知您正在使用的某些包没有类型提示,而不是 mypy 盲目地推断和涂抹
Any
遍布您的代码。不过,至少在大多数情况下,Mypy 可以 在这里给出更好的错误消息。 IMO 没有这样做的事实在很大程度上是一种疏忽。在 https://github.com/python/mypy/issues/4542 中对此进行了一些讨论。