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