Python导入的无限循环;寻找Pythonic方式

时间:2012-09-18 09:43:14

标签: python architecture import infinite-loop

我的团队正在与Django合作开展大型项目。为简单起见,这里用普通的Python来说明问题(原始问题有模型和应用程序而不是类(我知道两者都是类)和包(我知道两者都是包))。

a.py

from b import B1


class A1(object):
    def __init__(self):
        print "object A1"


class A2(object):
    def __init__(self):
        print "object A2"


A1()
B1()

b.py

from a import A2


class B1(object):
    def __init__(self):
        print "object B1"


A2()

当调用 a.py 时,它会尝试从 b 包导入 B1 ,另一方面,尝试导入 b 来自 a 包的em> A2 然后,从开始,它将永远重复。 Python说:

[dagrevis@localhost recursion]$ python2 a.py
Traceback (most recent call last):
  File "a.py", line 1, in <module>
    from b import B1
  File "/home/dagrevis/Python/recursion/b.py", line 1, in <module>
    from a import A2
  File "/home/dagrevis/Python/recursion/a.py", line 1, in <module>
    from b import B1
ImportError: cannot import name B1

其中一个解决方案是每个对象有一个文件。像C ++或Java这样的东西。然后我想起了Guido关于Python的内容:“不要在Python中编写Java(或C ++,或Javascript,...)。”是否有更多的Pythonic方法来处理这个问题?

感谢任何建议!

2 个答案:

答案 0 :(得分:4)

您的用例不是“可解决的”。您可以将ImportError转换为AttributeError导入模块a(和b),而不是导入对象,但这并不会改变您无法使用的事实使用这些模块。

问题是您的模块a要求在导入之前完全执行b,而b请求a要在导入之前完全执行。

这根本不可能解决,这是一个明确的症状,需要重构:您的ab模块应该是一个单独的模块(或者您可能想要进行更深层次的重构)

编辑: 实际上你可以解决这个问题,即使我认为这样做很难看,在需要的时候将导入放在文件的末尾。 但我认为这只是一个更大问题的补丁。

答案 1 :(得分:1)

您的示例过于简化 - 它无法解释为什么需要进行周期性导入。但无论如何,这是将其重构为可运行代码的一种方法:

a.py:

class A1(object):
    def __init__(self):
        print "object A1"


class A2(object):
    def __init__(self):
        print "object A2"

b.py:

class B1(object):
    def __init__(self):
        print "object B1"

c.py:

from a import A1, A2
from b import B1

A1()
A2()
B1()