Circular (or cyclic) imports in Python

前端 未结 12 2384
醉梦人生
醉梦人生 2020-11-21 05:23

What will happen if two modules import each other?

To generalize the problem, what about the cyclic imports in Python?

相关标签:
12条回答
  • 2020-11-21 05:45

    I got an example here that struck me!

    foo.py

    import bar
    
    class gX(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 <module>
        import foo
      File "/home/xolve/foo.py", line 1, in <module>
        import bar
      File "/home/xolve/bar.py", line 1, in <module>
        from foo import gX
    ImportError: cannot import name gX
    
    0 讨论(0)
  • 2020-11-21 05:46

    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.

    0 讨论(0)
  • 2020-11-21 05:53

    I solved the problem the following way, and it works well without any error. Consider two files a.py and b.py.

    I added this to a.py and it worked.

    if __name__ == "__main__":
            main ()
    

    a.py:

    import b
    y = 2
    def main():
        print ("a out")
        print (b.x)
    
    if __name__ == "__main__":
        main ()
    

    b.py:

    import a
    print ("b out")
    x = 3 + a.y
    

    The output I get is

    >>> b out 
    >>> a out 
    >>> 5
    
    0 讨论(0)
  • 2020-11-21 05:57

    If you do import foo (inside bar.py) and 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 bar.py) and 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.

    0 讨论(0)
  • 2020-11-21 05:57

    Module a.py :

    import b
    print("This is from module a")
    

    Module b.py

    import a
    print("This is from module b")
    

    Running "Module a" will output:

    >>> 
    'This is from module a'
    'This is from module b'
    'This is from module a'
    >>> 
    

    It output this 3 lines while it was supposed to output infinitival because of circular importing. What happens line by line while running"Module a" is listed here:

    1. The first line is import b. so it will visit module b
    2. The first line at module b is import a. so it will visit module a
    3. The first line at module a is import b but note that this line won't be executed again anymore, because every file in python execute an import line just for once, it does not matter where or when it is executed. so it will pass to the next line and print "This is from module a".
    4. After finish visiting whole module a from module b, we are still at module b. so the next line will print "This is from module b"
    5. Module b lines are executed completely. so we will go back to module a where we started module b.
    6. import b line have been executed already and won't be executed again. the next line will print "This is from module a" and program will be finished.
    0 讨论(0)
  • 2020-11-21 05:57

    Suppose you are running a test python file named request.py In request.py, you write

    import request
    

    so this also most likely a circular import.

    Solution Just change your test file to another name such as aaa.py, other than request.py.

    0 讨论(0)
提交回复
热议问题