Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive import: 'import' vs. 'from ... import ...'

I have two files that need to use different functions from each other.

file1.py:

import file2   # from file2 import y2

def x1():
    print "x1"

def x2():
    print "x2"
    file2.y2()

file2.py:

import file1   # from file1 import x1

def y1():
    file1.x1()
    print "y"

def y2():
    print "y2"

if __name__ == "__main__":
    y1()

I would like to know why using import file1 is working, but importing just the specific function from file1 (from file1 import x1) is not?

Traceback (most recent call last):
  File "file2.py", line 1, in <module>
    from file1 import x1
  File "file1.py", line 1, in <module>
    import file2
  File "file2.py", line 1, in <module>
    from file1 import x1
ImportError: cannot import name x1

I've read this about imports:

import X

Imports the module X, and creates a reference to that module in the current namespace. Then you need to define completed module path to access a particular attribute or method from inside the module (e.g.: X.name or X.attribute)

from X import *

Imports the module X, and creates references to all public objects defined by that module in the current namespace (that is, everything that doesn’t have a name starting with _) or whatever name you mentioned.

Or, in other words, after you've run this statement, you can simply use a plain (unqualified) name to refer to things defined in module X. But X itself is not defined, so X.name doesn't work. And if name was already defined, it is replaced by the new version. And if name in X is changed to point to some other object, your module won’t notice.

This makes all names from the module available in the local namespace.

like image 423
Iulian Stana Avatar asked Mar 25 '16 11:03

Iulian Stana


1 Answers

Cyclic imports usually indicate design problems but in order to solve them you may write the import statement at the bottom like so:

def x1():
    print "x1"

def x2():
    print "x2"
    file2.y2()

from file2 import y2

Keep in mind it's a workaround. The reason from x import y doesn't work in case of cyclic imports is that when you reach the first from ... import ... you are passed to the second module and when the second module calls back the first, the interpreter realizes it's a never-ending cycle and continues with a partially imported module, which happens before you even define the functions meaning y2 doesn't exist yet.

like image 121
Bharel Avatar answered Oct 02 '22 22:10

Bharel