Circular (or cyclic) imports in Python
If you do
import foo (inside
import bar (inside
foo.py), it will work fine. By the time anything actually runs, both modules will be fully loaded and will have references to each other.
The problem is when instead you do
from foo import abc (inside
from bar import xyz (inside
foo.py). Because now each module requires the other module to already be imported (so that the name we are importing exists) before it can be imported.
There was a really good discussion on this over at comp.lang.python last year. It answers your question pretty thoroughly.
Imports are pretty straightforward really. Just remember the following:
'import' and 'from xxx import yyy' are executable statements. They execute when the running program reaches that line.
If a module is not in sys.modules, then an import creates the new module entry in sys.modules and then executes the code in the module. It does not return control to the calling module until the execution has completed.
If a module does exist in sys.modules then an import simply returns that module whether or not it has completed executing. That is the reason why cyclic imports may return modules which appear to be partly empty.
Finally, the executing script runs in a module named __main__, importing the script under its own name will create a new module unrelated to __main__.
Take that lot together and you shouldn't get any surprises when importing modules.
Cyclic imports terminate, but you need to be careful not to use the cyclically-imported modules during module initialization.
Consider the following files:
print "a in"import sysprint "b imported: %s" % ("b" in sys.modules, )import bprint "a out"
print "b in"import aprint "b out"x = 3
If you execute a.py, you'll get the following:
$ python a.pya inb imported: Falseb ina inb imported: Truea outb outa out
On the second import of b.py (in the second
a in), the Python interpreter does not import
b again, because it already exists in the module dict.
If you try to access
a during module initialization, you will get an
Append the following line to
Then, the output is:
$ python a.pya in b imported: Falseb ina inb imported: Truea outTraceback (most recent call last): File "a.py", line 4, in <module> import b File "/home/shlomme/tmp/x/b.py", line 2, in <module> import a File "/home/shlomme/tmp/x/a.py", line 7, in <module> print b.xAttributeError: 'module' object has no attribute 'x'
This is because modules are executed on import and at the time
b.x is accessed, the line
x = 3 has not be executed yet, which will only happen after