many ways to import a module Link to heading
import X
Link to heading
imports module X, and creates a reference to module in current namespace.
from X import a, b, c
Link to heading
imports module X and creates references in the current namespace to given objects, in this case a, b, c.
what does python do to import module Link to heading
if module has already registered (sys.modules), it just passes.
else,
- create new module object in dict
- load module object
- execute the module code in the new module’s namespace
what is a circular dependency Link to heading
two or more modules depend on each other. For example:
functionA():
functionB()
functionB():
functionA()
---------------
| |
v |
functionA functionB
| ^
| |
---------------
Cons Link to heading
tight coupling between modules, so that reduced code reusability
source of potential failures, such as infinite recursions, memory leaks and cascade effects.
very difficult to debug and very hard to realize it is something related to circular imports.
what is a circular import Link to heading
see below three python files
#__init__.py
import module1
module1.function1()
#module1.py
import module2
def function1():
module2.function2()
def function3():
print('Goodbye, World!')
#module2.py
import module1
def function2():
print('Hello, World!')
module1.function3()
executing:
$ python __init__.py
Hello, World!
Traceback (most recent call last):
File "__init__.py", line 3, in <module>
module1.function1()
File "/Users/scott/projects/sandbox/python/circular-dep-test/module1/__init__.py", line 5, in function1
module2.function2()
File "/Users/scott/projects/sandbox/python/circular-dep-test/module2/__init__.py", line 6, in function2
module1.function3()
AttributeError: 'module' object has no attribute 'function3'
When Python imports a module, it checks the module registry to see if the module was already imported. If the module was already registered, Python uses that existing object from cache. The module registry is a table of modules that have been initialized and indexed by module name. This table can be accessed through sys.modules.
If it was not registered, Python finds the module, initializes it if necessary, and executes it in the new module’s namespace.
Modules are executed during import, and new functions and classes won’t appear in the module’s namespace until the def (or class) statement has been executed.
in this case, let’s analyze it.
__init__.py import module 1, so sys.modules contains module 1(empty). module 1 imports module2, so sys.modules contains module 2 (empty). next def will be executed, it calls module1.function3(). But notes that module 1 is empty right now in dict.
How to fix circular dependencies/imports Link to heading
Simple solution, not for flask or anyother framework:
- merge modules together to a larger module.
However, merged module may have unrelated functions, this is called tight coupling.
- Another solution is to import only needed. The above file can be rewritten as
# module 1
def function1():
import module2
module2.function2()
def function3():
print('Goodbye, World!')
- in flask, people tend to import at last to avoid circular imports