Python - Circular (or cyclic) imports in Python

Today I am going to explain What will happen if two modules import each other?

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.
If you do "import foo" inside bar and "import bar" inside foo, 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" and "from bar import xyz". Because now each module requires the other module to already be compiled (so that the name we are importing exists) before it can be compiled.

I got an example here that struck me! foo.py

            import bar
            
            class GO(object):
               g = 10
             
bar.py

            from foo import gX
            
            o = gX()
            
main.py

            import foo
            import bar
            
            print "all done"
            
At the command line: $ python main.py

            *Traceback (most recent call last):
             File "m.py", line 1, in 
               import foo
             File "/home/xolve/foo.py", line 1, in 
               import bar
             File "/home/xolve/bar.py", line 1, in 
               from foo import gX
            ImportError: cannot import name gX*
            

Leave a comment