【问题标题】:How can I get mypy to either recognize or ignore dynamically imported types?如何让 mypy 识别或忽略动态导入的类型?
【发布时间】:2018-08-06 01:02:51
【问题描述】:

我有一个 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 时,我得到了

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

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

此时,我根本无法让mypy 成功通过。我能做些什么来解决这个问题?

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

【问题讨论】:

  • 我猜创建存根文件 (src/m/a.pyi) 是不可能的?
  • @mgilson 不幸的是,是的。我正在创建的类型集是dynamic,因此在存根文件中枚举它们会破坏目的。

标签: python types mypy type-annotation


【解决方案1】:

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

您的选择包括:

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

    这样,您至少会为模块 b 中的实际变量分配一些东西(尽管“某物”的类型只是 Any)。

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

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

【讨论】:

  • 嗯。我不认为 1 会起作用,因为我正在按照here 的描述动态构建类型,所以我不知道A 是什么。我设法让 2 工作(以前我在让 mypy 和 pylint 都忽略它时遇到问题)。我实际上没有尝试过使用元类(目前它有点超出我的 Python 专业知识)。如果您有任何想法如何在不使用 exec 的情况下解决我的其他问题,我很想听听。目前只有一个答案。
  • @KrisHarper -- 老实说,我不完全确定您要解决什么问题。 (例如,我知道您正在尝试动态创建类型,但并不真正理解为什么)。不过,如果您解释一下您正在做的事情背后的一些背景/背景,我很乐意尝试提供更有针对性的建议。
  • 是的,当然。实际的问题是我们所有的数据库表都有 SQLAlchemy 模型。这些表中的每一个在单独的架构中都有一个单独的审计表。审计表具有与真实表完全相同的名称和相同的列集,以及少数审计表特定的列,如更新时间等。我想到了自动为审计表创建所有模型他们自己的模块(在这种情况下为a.py)并在其他模块中使用它们(在这种情况下为b.py)。
  • 我能够使用单个表来实现这一点,但我需要遍历模型模块中的所有模型并动态创建新类型。当我这样做时,我无法导入这些类型,因此这是我第一个问题的前提。我不喜欢使用exec 的想法,但这就是我目前所能做的。
  • @KrisHarper -- 是的,看起来你已经达到了 mypy 可以做的极限。如果您真的想要审计表的静态类型,最好的办法可能是手动编码每个新模型——也许您可以将每个审计模型子类化为相应的非子类,以帮助减少重复。诚然,这乏味的,具体取决于您有多少张桌子/计划添加新桌子的频率。
猜你喜欢
  • 2021-11-09
  • 2022-07-23
  • 2020-08-02
  • 1970-01-01
  • 2021-05-17
  • 2021-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多