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

时间:2019-09-04 09:30:51

标签: 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'

但是当尝试使用完全相同的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看到确实存在的可导入模块?

2 个答案:

答案 0 :(得分:1)

因此,这是问题的症结所在:mypy不会尝试对已导入的每个模块进行类型检查。相反,它仅尝试对已经明确选择加入类型生态系统的模块进行类型检查。

模块可以通过两种关键机制选择加入打字生态系统:

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

aws_xray_sdk软件包没有完成这两项操作,因此将被mypy忽略。


这有点不幸,那么您该怎么办? mypy文档的Missing imports部分提供了一些具体的操作建议,但总而言之,您基本上会列出三个选项,从最小到最大的努力依次列出:

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

    [mypy-aws_xray_sdk]
    ignore_missing_imports = True
    

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

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

  3. 为此库创建自己的存根,然后通过mypy配置文件中的mypy_path选项指向它们:

    mypy_path = my_stubs/aws_xray_sdk, my_stubs/some_other_library
    

    这些存根不一定必须是完整的:您可以为正在使用的一些东西添加注释而摆脱困境。 (如果它们最终变得相对完整,那么您可能会考虑将它们贡献给开源社区。)


现在终于,您可能想知道为什么 mypy的行为方式如此?

部分原因是因为通常情况下,mypy仅尝试查找和分析模块并不安全。盲目地导入和使用尚未准备好类型提示的软件包有时会导致奇数类型错误,甚至更糟的是,可能导致代码被错误地标记为类型安全。也就是说,如果您关心类型安全,最好立即通知您正在使用的某些程序包没有类型提示,而不是mypy盲目地推断和涂抹整个代码Any

但是,至少在大多数情况下,

Mypy 可以在此处给出更好的错误消息。 IMO事实并非如此,这实际上是一个疏忽。 https://github.com/python/mypy/issues/4542中对此有一些讨论。

答案 1 :(得分:1)

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

我遇到了同样的问题,并意识到我试图从中导入的包缺少 __init__.py 文件。因此,mypy 无法“看到”导入。