如何让 mypy 识别或忽略动态导入的类型?

How can I get mypy to either recognize or ignore dynamically imported types?

我有一个具有以下结构的 Python 项目

src/
  __init__.py
  m/
    __init__.py
    a.py
    b.py

src/m/__init__.py的内容是

exec_str = 'A = type("A", (object,), {"x": 1})'

src/m/a.py的内容是

from src.m import exec_str
exec(exec_str)

src/m/b.py的内容是

from src.m.a import A

当我 运行 mypy 反对此代码时,我得到

error: Module 'src.m.a' has no attribute 'A'

我不确定是否有办法让 mypy 识别这个模块。我知道我正在动态创建和导入一个类型,所以我不一定期望 mypy 在这里工作,但我也不知道如何让 mypy 忽略它。我尝试添加 # type: ignore,但 mypy 说 misplaced type annotation.

至此,我根本无法mypy顺利通过。我该怎么做才能解决这个问题?

我还应该说,如果可能的话,我真的不想忽略所有 b.py。那里(实际上)有相当多的代码可以很好地进行类型检查。

不幸的是,您在这里没有太多好的选择 -- mypy 不能真正处理动态构造的类型。

您的选择包括:

  1. 修改 exec_str 使其只读取 exec_str = 'exec("A", (object,), {"x": 1})' 然后在模块 a 或 b 中执行 A = exec(exec_str)

    这样,您至少会为模块 b 中的实际变量分配一些内容(尽管 "something" 将只是 Any 类型)。

  2. # type: ignore 注释专门添加到导入中。 from src.m.a import A # type: ignore 也是如此。

  3. 重组您的代码以降低必要的动态量或使用不同的元编程工具来完成相同的任务。例如,Mypy 对元类有基本的了解。 (我假设您已经考虑过这个选项,但我认为为了完整起见我应该提及它)。