如何修复导入的循环依赖项

时间:2010-09-17 23:05:08

标签: python import python-3.x circular-dependency

我有三个文件:

testimports模块:

#import moduleTwo
import moduleOne

hiString = "Hi!"

moduleOne.sayHi()

ModuleONE中:

import moduleTwo

class sayHi():
    moduleTwo.printHi()

ModuleTWO中:

import testimports

def printHi():
    print(testimports.hiString)

如果我运行testimports,我会:

Traceback (most recent call last):
  File "..file path snipped../testimports/src/testimports.py", line 2, in <module>
    import moduleOne
  File "..file path snipped../testimports/src/moduleOne.py", line 1, in <module>
    import moduleTwo
  File "..file path snipped../testimports/src/moduleTwo.py", line 1, in <module>
    import testimports
  File "..file path snipped../testimports/src/testimports.py", line 6, in <module>
    moduleOne.sayHi()
AttributeError: 'module' object has no attribute 'sayHi'

但是,如果我取消注释import moduleTwo中的testimports行,程序会在它停止工作之前达到这一点:

Traceback (most recent call last):
  File "..file path snipped../testimports/src/testimports.py", line 1, in <module>
    import moduleTwo
  File "..file path snipped../testimports/src/moduleTwo.py", line 1, in <module>
    import testimports
  File "..file path snipped../testimports/src/testimports.py", line 2, in <module>
    import moduleOne
  File "..file path snipped../testimports/src/moduleOne.py", line 3, in <module>
    class sayHi():
  File "..file path snipped../testimports/src/moduleOne.py", line 4, in sayHi
    moduleTwo.printHi()
AttributeError: 'module' object has no attribute 'printHi'

我如何解决这个循环依赖问题?

3 个答案:

答案 0 :(得分:9)

verisimilidude正朝着正确的方向前进。我会扩展一点以提供更多细节。

在这两种情况下,都会发生这种情况:

  1. testimports执行为__main__
  2. testimports导入moduleOne。现在moduleOne从文件中读取并添加到导入的模块列表sys.modules
  3. 导入moduleOne开始执行moduleTwo的导入。现在从文件中读取moduleTwo并将其添加到导入的模块列表sys.modules中。请注意,此阶段moduleOne的其余部分尚未执行,因此未定义sayHi
  4. 现在moduleTwo通过导入testimports开始执行。这是第一次导入testimports,与__main__无关。它现已插入sys.modules
  5. 这是事情变得有趣的地方。新导入的testimports导入moduleOne但是moduleOne已经在sys.modules 中,因此不会再次阅读。然后执行进行到行moduleOne.sayHi()moduleOne的导入尚未完成,sayHi尚未定义。因此我们得到错误。
  6. 如果取消注释moduleTwo,则会发生类似的循环。实质上,__main__导入moduleTwo导入testimports,导入已导入的moduleTwo导入并导入moduleOne;然后导入moduleTwo,然后尝试调用尚未定义的moduleTwo.printHi,因为moduleTwo还没有完成执行。

    Anatoly Rr的解决方案通过使模块testimports在导入时不调用任何其他模块功能来解决所有这些问题。因此,当moduleTwo导入它时,它不会调用moduleOne.sayHi。只有在__main__启动时才执行该操作,以便在所有导入后执行被延迟。

    故事的寓意? Avoid circular dependencies in Python if possible

答案 1 :(得分:2)

重写testimports.py可能有所帮助:

import moduleOne

hiString = "Hi!"

def main ():
    moduleOne.sayHi()

if __name__ == "__main__":
    main ()

答案 2 :(得分:2)

你的问题是,当Python导入某些内容时,它会在基本级别执行所有语句。再次分配hiString,并在Module3将原始testimports.py作为模块导入时再次进行调用。 Anatoly Rr的解决方案有效,因为调用现在在def中。不调用def,因为__name__向Python运行时指示正在导入模块。从命令行调用它时,它的模块名称为__main__