如何允许 Python3.5+ 中的相对循环导入仅用于数据类类型检查?

How to allow relative circular imports in Python3.5+ used only for dataclass type checks?

我的文件结构如下:

├── test_package
│   ├── __init__.py
│   └── models
│       ├── __init__.py
│       ├── a.py
│       └── b.py

以及以下文件内容:

# a.py
from .b import B
from dataclasses import dataclass

@dataclass
class A:
    b: B

# b.py
from .a import A
from dataclasses import dataclass

@dataclass
class B:
    a: A

尝试导入包 a 时,出现以下错误。

: import test_package.models.a                                                                 
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-1-e8165f4eb507> in <module>
----> 1 import test_package.models.a

/.../test_package/models/a.py in <module>
----> 1 from .b import B
      2 from dataclasses import dataclass
      3 
      4 @dataclass
      5 class A:

/.../test_package/models/b.py in <module>
----> 1 from .a import A
      2 from dataclasses import dataclass
      3 
      4 @dataclass
      5 class B:

ImportError: cannot import name 'A' from 'test_package.models.a'

根据 Python3.5 change log,"Circular imports involving relative imports are now supported. (Contributed by Brett Cannon and Antoine Pitrou in bpo-17636.)" 我如何使这个相对循环导入工作?

请注意,我只需进行这些导入即可进行类型检查。

编辑:

作为对评论中@juanpa.arrivillaga 的回复,这里是 Python 2.7 发生相同错误的示例。除非我误解了某些东西,否则源文件似乎正在被找到并被执行。

$ cat a.py
from b import b_func

def a_func():
    return "Hi"

$ cat b.py
from a import b_func

def b_func():
    return "Hi"

>>> import a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "a.py", line 1, in <module>
    from b import b_func
  File "b.py", line 1, in <module>
    from a import b_func
ImportError: cannot import name b_func

"When a type hint contains names that have not been defined yet, that definition may be expressed as a string literal, to be resolved later." 例如,

@dataclass 
class A: 
    b: 'B' 

@dataclass 
class B: 
    a: A

>>> A.__annotations__ # This is what the type checker uses
{'b': 'B'} 

有关详细信息,请参阅 https://www.python.org/dev/peps/pep-0484/#forward-references

请注意,这不是我提出的问题的答案,但这是我希望得到的答案。所以我发布了这个答案,以防有人和我走同样的路。