【问题标题】:Infinite loop with Python imports; looking for Pythonic way带有 Python 导入的无限循环;寻找 Pythonic 方式
【发布时间】:2012-09-10 13:28:35
【问题描述】:

我的团队正在使用 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,另一方面,它会尝试导入 A2 来自 a 包,然后从头开始,永远重复。 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 方式来处理这个问题?

感谢您的任何建议!

【问题讨论】:

标签: python architecture import infinite-loop


【解决方案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()

【讨论】:

    【解决方案2】:

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

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

    这是根本无法解决的,这是需要重构的明显症状:您的 ab 模块应该是单个模块(或者您可能想要进行更深入的重构)。

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

    【讨论】:

    • 你的回答比我的更清晰准确,我会删除我的。
    猜你喜欢
    • 2019-03-14
    • 1970-01-01
    • 2016-05-12
    • 1970-01-01
    • 2014-12-29
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    相关资源
    最近更新 更多