Two Python modules require each other's contents - can that work?
Modules can import each other cyclically, but there's a catch. In the simple case, it should work by moving the import
statements to the bottom of the file or not using the from
syntax.
Here's why that works:
When you import a module, Python first checks sys.modules
. If it's in there, it just imports from there. If it's not there, it tries to import it in the normal way; basically, it finds the file and runs the stuff in it.
Running a module populates the module's contents. For example, say we have this module, creatively named example_opener
:
import webbrowser
def open_example():
webbrowser.open('http://www.example.com/')
At the start, the module is empty. Then Python executes:
import webbrowser
After that, the module only contains webbrowser
. Then Python executes this:
def open_example():
webbrowser.open('http://www.example.com/')
Python creates open_example
. Now the module contains webbrowser
and open_example
.
Say webbrowser
contained this code:
from example_opener import open_example
def open(url):
print url
Say example_opener
is imported first. This code is executed:
import webbrowser
webbrowser
has not yet been imported, so Python executes the contents of webbrowser
:
from example_opener import open_example
example_opener
has been imported, but not yet fully executed. Python doesn't care. Python pulls the module out of sys.modules
. At this point, example_opener
is still empty. It hasn't defined open_example
yet, nor even completed importing webbrowser
. Python can't find open_example
in example_opener
, so it fails.
What if we imported open_example
from the end of webbrowser
and webbrowser
from the end of example_opener
? Python would start by executing this code:
def open_example():
webbrowser.open('http://www.example.com/')
webbrowser
does not exist yet, but it doesn't matter until open_example
is called. Now example_opener
contains only open_example
. It then executes:
import webbrowser
It has not been imported yet, so Python executes webbrowser
. It starts:
def open(url):
print url
It defines open
. Then it executes:
from example_opener import open_example
example_opener
is in sys.modules
, so it uses that. example_opener
contains open_example
, so it succeeds. Python finishes importing webbrowser
. That concludes importing webbrowser
from example_opener
. That's the last thing in example_opener
, so the import of example_opener
finishes, successful, as well.
Don't do from ... import ...
. Just do import ...
and reference its objects using the module name.