Skip to content

Instantly share code, notes, and snippets.

@angusb
Created November 29, 2012 22:00
Show Gist options
  • Save angusb/4172194 to your computer and use it in GitHub Desktop.
Save angusb/4172194 to your computer and use it in GitHub Desktop.
circular python imports
# a.py
print '1a'
import b
print '2a'
x = b.x + 1
# b.py
print '1b'
import a
print '2b'
x = 1
"""
Rules for dealing with cyclical imports:
* 'import' and 'from x import y' are executable statements. They execute
when the program reaches their line.
* If a module is not in sys.modules, then an import creates a new entry
in sys.modules and 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 returns it,
regardless of whether the module has completed executing. This results
in modules which appear to be partly empty.
* The executing script runs in a module named __main__. Importing the
script under its own name will create a new module unrelated to __main__.
"""
# ./a.py
1a
# load b into sys.modules, run b
1b
# load a into sys.modules, run a
1a
# find b in sys.modules, return it
2a
# AttributeError: 'module' object has no attribute 'x'
# ./b.py
1b
# load a into sys.modules, run a
1a
# load b into sys.modules, run b
1b
# find a in sys.modules, return it
2b
x = 1
2a
x = b.x + 1
2b # See note below
x = 1
# Note: the reason that the '2b' is printed again (and x = 1 is executed)
# is due to rule 2. It's at this point that control finally 'unwinds' to
# where module b first imports module a.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment