4

I have a Python project with the following structure

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

The contents of src/m/__init__.py are

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

The contents of src/m/a.py are

from src.m import exec_str
exec(exec_str)

The contents of src/m/b.py are

from src.m.a import A

When I run mypy against this code I get

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

I'm not sure if there's a way to get mypy to recognize this module. I understand that I'm dynamically creating and importing a type, so I don't necessarily expect mypy to work here, but I also don't know a way to get mypy to ignore it. I tried adding # type: ignore, but mypy says misplaced type annotation.

At this point, I can't get mypy to successfully pass at all. What can I do to get around this?

I should also say, I'd really rather not ignore all of b.py if possible. There's a decent amount of code in there (in reality) that would be good to type check.

4

1 回答 1

1

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

您的选择包括:

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

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

  2. # type: ignore注释专门添加到导入中。就这样吧from src.m.a import A # type: ignore

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

于 2018-08-06T14:40:49.790 回答