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

Python 如何让mypy识别或忽略动态导入的类型?,python,types,mypy,type-annotation,Python,Types,Mypy,Type Annotation,我有一个Python项目,其结构如下 src/ __init__.py m/ __init__.py a.py b.py src/m/_init__.py的内容如下 exec_str = 'A = type("A", (object,), {"x": 1})' from src.m import exec_str exec(exec_str) from src.m.a import A src/m/a.py的内容如下 exec_str = 'A = typ

我有一个Python项目,其结构如下

src/
  __init__.py
  m/
    __init__.py
    a.py
    b.py
src/m/_init__.py
的内容如下

exec_str = 'A = type("A", (object,), {"x": 1})'
from src.m import exec_str
exec(exec_str)
from src.m.a import A
src/m/a.py
的内容如下

exec_str = 'A = type("A", (object,), {"x": 1})'
from src.m import exec_str
exec(exec_str)
from src.m.a import A
src/m/b.py
的内容如下

exec_str = 'A = type("A", (object,), {"x": 1})'
from src.m import exec_str
exec(exec_str)
from src.m.a import A
当我针对这个代码运行
mypy
时,我得到

错误:模块“src.m.a”没有属性“a”

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

此时,我根本无法让
mypy
成功通过。我能做些什么来避开这件事


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

不幸的是,这里没有太多好的选项——mypy无法真正处理动态构造的类型

你的选择包括:

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

    这样,您至少将为模块b中的实际变量赋值(尽管“something”将是Any类型)

  • #type:ignore
    注释专门添加到导入中。因此,请从src.m.a导入一个#type:ignore

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


  • 我猜创建存根文件(
    src/m/a.pyi
    )是不可能的?@mgilson不幸的是,是的。我正在创建的类型集是,因此在存根文件中枚举它们将无法达到此目的。我认为1不起作用,因为我正在按照描述动态构造类型,所以我不知道
    A
    是什么。我设法让2个工作(之前我遇到了让mypy和pylint忽略它的问题)。实际上,我还没有尝试过使用元类(这有点超出了我在Python方面的专业知识)。如果您有任何想法如何解决我的其他问题而不使用exec,我很乐意听到。目前只有一个答案。@KrisHarper——老实说,我不完全确定你到底想解决什么问题。(例如,我知道您正在尝试动态创建类型,但并不真正理解原因)。不过,如果你能解释一下你所做的事情背后的背景/背景,我很乐意尝试给出更有针对性的建议。实际的问题是,我们的所有数据库表都有SQLAlchemy模型。这些表中的每一个在单独的模式中都有一个单独的审计表。审计表与实际表具有完全相同的名称和相同的列集,以及一些特定于审计表的列,如更新时间等。我的想法是在自己的模块中自动为审计表创建所有模型(
    a.py
    ),并在其他模块中使用它们(
    b.py
    在这种情况下)。我能够在单个表中实现这一点,但我需要在模型模块中循环所有模型并动态创建新类型。当我这样做时,我无法导入这些类型,这就是我第一个问题的前提。我不喜欢使用
    exec
    ,但这就是我在mom中所能得到的全部ent.@KrisHarper--是的,看起来你已经达到了mypy的极限。如果你真的想要审计表的静态类型,最好的办法可能是手动编写每个新模型的代码——也许你可以让每个审计模型的子类与相应的非子类相对应,以帮助减少重复。这是公认的乏味,这取决于您有多少个表/您计划添加新表的频率。