0

我有三个文件:

测试导入模块:

#import moduleTwo
import moduleOne

hiString = "Hi!"

moduleOne.sayHi()

模块一:

import moduleTwo

class sayHi():
    moduleTwo.printHi()

模块二:

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 moduleTwotestimports,程序会在停止工作之前到达这一点:

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'

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

4

3 回答 3

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. 这就是事情变得有趣的地方。新进口的进口testimportsmoduleOnemoduleOne已在 中sys.modules,因此不再读取。然后执行进行到行moduleOne.sayHi()但是导入moduleOne还没有完成,sayHi也没有定义。因此我们得到了错误。

如果moduleTwo未注释,则会发生类似的循环。本质上,__main__import moduleTwowhich import testimportswhich 通过 import 的moduleTwo已经被导入和导入moduleOne;依次导入moduleTwo然后尝试调用moduleTwo.printHi尚未定义的哪个,因为moduleTwo一直没有完成执行。

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

这个故事的主旨?尽可能避免 Python 中的循环依赖

于 2010-09-18T00:25:01.453 回答
2

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

import moduleOne

hiString = "Hi!"

def main ():
    moduleOne.sayHi()

if __name__ == "__main__":
    main ()
于 2010-09-17T23:15:33.193 回答
2

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

于 2010-09-17T23:37:41.223 回答