Python 包装中循环导入的正确方式(适用于pep-0484)

Python 包装中循环导入的正确方式(适用于pep-0484),python,python-3.x,Python,Python 3.x,我试图找出一种(以及)正确使用python(3.4)包中的循环导入的方法。我完全理解,循环导入通常表示代码未完全分离到模块中,但是使用PEP-0484进行注释/类型暗示将导致大量循环导入(我认为)完全合理的代码。在这种情况下,通常建议的将导入放在函数中或模块底部的解决方案也不起作用 简单案例(无包装,无循环导入): 添加PEP-0484(无包装、循环导入、需要): 到目前为止,一切顺利。但是现在我想把它做成一个包,我不能让它工作 [pack/__init__.py] (empty) [pack/

我试图找出一种(以及)正确使用python(3.4)包中的循环导入的方法。我完全理解,循环导入通常表示代码未完全分离到模块中,但是使用PEP-0484进行注释/类型暗示将导致大量循环导入(我认为)完全合理的代码。在这种情况下,通常建议的将导入放在函数中或模块底部的解决方案也不起作用

简单案例(无包装,无循环导入):

添加PEP-0484(无包装、循环导入、需要):

到目前为止,一切顺利。但是现在我想把它做成一个包,我不能让它工作

[pack/__init__.py] (empty)
[pack/a.py]
from . import b
class A:
    def __init__(self):
        self.b = b.B(self)
    def get_b() -> b.B:
        return self.b
[pack/b.py]
from . import a
class B:
    def __init__(self, parent: "a.A"):
        self.parent = parent
[main.py]
from model import a
print(a.A())
运行
python main.py
的结果是

Traceback (most recent call last):
  File "main.py", line 1, in <module>
    from model import a
  File "/private/tmp/circ/model/a.py", line 1, in <module>
    from . import b
  File "/private/tmp/circ/model/b.py", line 1, in <module>
    from . import a
ImportError: cannot import name 'a'
回溯(最近一次呼叫最后一次):
文件“main.py”,第1行,在
从模型导入a
文件“/private/tmp/circ/model/a.py”,第1行,在
从…起进口b
文件“/private/tmp/circ/model/b.py”,第1行,在
从…起导入
ImportError:无法导入名称“a”
我的问题是:

  • 我不明白为什么这个错误会失败。就我阅读导入内部代码的理解而言,
    来自。导入
    b.py中的
    应该会导致导入一个空模块,只有在模块
    b
    完全导入后才会填充,这是可以的
  • 解决这个问题的正确方法是什么?我需要参考
    b
    模块范围中的
    a
    ,反之亦然。无论我尝试相对路径和绝对路径的组合是什么,从
    \uuu init\uuuu.py
    文件导入这两个模块,甚至将该文件一起删除,我似乎都无法运行

第一个问题由这个问题的(非常详细的!)答案回答:python 3.5似乎更允许这种循环导入,而且由于PEP-0484是python 3.5的东西,所以这个问题可能不太有效。尽管如此,在3.2中使用pep-0484样式的注释仍然有很大的优势请参见:现在支持涉及相对导入的循环导入。(由Brett Cannon和Antoine Pitrou在17636期中提供。)
[pack/__init__.py] (empty)
[pack/a.py]
from . import b
class A:
    def __init__(self):
        self.b = b.B(self)
    def get_b() -> b.B:
        return self.b
[pack/b.py]
from . import a
class B:
    def __init__(self, parent: "a.A"):
        self.parent = parent
[main.py]
from model import a
print(a.A())
Traceback (most recent call last):
  File "main.py", line 1, in <module>
    from model import a
  File "/private/tmp/circ/model/a.py", line 1, in <module>
    from . import b
  File "/private/tmp/circ/model/b.py", line 1, in <module>
    from . import a
ImportError: cannot import name 'a'