How to fix a circular dependency for imports
I have three files:
testimports module:
#import moduleTwo
import moduleOne
hiString = "Hi!"
moduleOne.sayHi()
moduleOne:
import moduleTwo
class sayHi():
moduleTwo.printHi()
moduleTwo:
import testimports
def printHi():
print(testimports.hiString)
If I run testimports
, I get:
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'
If, however, I uncomment the import moduleTwo
line in testimports
, the program gets to this point before it stops working:
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 say开发者_Go百科Hi():
File "..file path snipped../testimports/src/moduleOne.py", line 4, in sayHi
moduleTwo.printHi()
AttributeError: 'module' object has no attribute 'printHi'
How would I go about resolving this circular dependency problem?
verisimilidude is along the right direction. I would expand a little to give more details.
In both cases, this is what happens:
testimports
is executed as__main__
testimports
importsmoduleOne
. NowmoduleOne
is read from file and added to the list of imported modulessys.modules
.- The execution of importing of
moduleOne
starts by importingmoduleTwo
. NowmoduleTwo
is read from file and added to the list of imported modulessys.modules
. Note at this stage the rest ofmoduleOne
hasn't been executed yet sosayHi
is not defined. - Now
moduleTwo
starts execution by importingtestimports
. This is the first timetestimports
is imported and it has nothing to do with it being the same as__main__
. It is now inserted intosys.modules
. - Here is where things get interesting. The newly imported
testimports
importsmoduleOne
. ButmoduleOne
is already insys.modules
, so it is not read again. Then the execution progresses to the linemoduleOne.sayHi()
. But the importing ofmoduleOne
hasn't finished andsayHi
is not yet defined. Hence we get the error.
A similar loop happens if moduleTwo
is uncommented. In essence, __main__
imports moduleTwo
which imports testimports
which passes the import of moduleTwo
which is already imported and imports moduleOne
; which in turn imports moduleTwo
and then tries to call moduleTwo.printHi
which isn't defined yet because moduleTwo
hasn't finished execution all this time.
Anatoly Rr's solution breaks all this by making the module testimports
not call any other module functionality when imported. So when it is imported by moduleTwo
it doesn't call moduleOne.sayHi
. Only when started as __main__
will it execute that so that execution is delayed after all the imports.
The moral of the story? Avoid circular dependencies in Python if possible.
Rewriting testimports.py
may help:
import moduleOne
hiString = "Hi!"
def main ():
moduleOne.sayHi()
if __name__ == "__main__":
main ()
Your problem is that when Python imports something it executes all statements at the base level. hiString is assigned to again and the call is made again when Module3 imports your original testimports.py as a module. Anatoly Rr's solution works because the call is now inside a def. The def is not called because the __name__
indicates to the Python runtime that the module is being imported. When it is being called from the command line it's module name would be __main__
.
精彩评论