2010-09-17 75 views
0

循环依赖我有三个文件:如何解决进口

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' 

我如何去解决这个圆依赖性问题?

+1

请搜索SO进行循环导入。有几百个问题就像你的问题。 http://stackoverflow.com/search?q=%5Bpython%5D+circular+import – 2010-09-18 12:58:22

+1

可能重复的[Python:Cyclic imports](http://stackoverflow.com/questions/744373/python-cyclic-imports) – 2010-09-18 12:58:46

回答

2

重写testimports.py可以帮助:

import moduleOne 

hiString = "Hi!" 

def main(): 
    moduleOne.sayHi() 

if __name__ == "__main__": 
    main() 
+0

谢谢!有效! :D – wrongusername 2010-09-17 23:20:59

2

你的问题是,当Python导入东西处执行的基本级别的所有语句。 hiString被重新分配,并且当Module3将原始testimports.py作为模块导入时再次进行调用。 Anatoly Rr的解决方案是可行的,因为这个调用现在在def中。 def未被调用,因为__name__向Python运行时指示正在导入模块。从命令行调用时,模块名称为__main__

+0

实际上并不准确。例如,hiString不会再次分配,但会有两个hiStrings。在这两种情况下,除了导入的testimports之外,还会有一个__ _ main _ \ _。详情请参阅我的回答。 – 2010-09-18 01:06:47

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进口moduleOnemoduleOne已在sys.modules,所以它不会再读取。然后执行进展到行moduleOne.sayHi()moduleOne的导入尚未完成,sayHi尚未定义。因此我们得到错误。

如果取消注释moduleTwo,则会发生类似的循环。实质上,__main__进口moduleTwo,其中进口testimports通过进口moduleTwo已进口和进口moduleOne;后者依次导入moduleTwo,然后尝试呼叫尚未定义的moduleTwo.printHi,因为moduleTwo尚未完成执行。

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

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