3

I have read several more questions on stackoverflow, but still don't understand.

From an example in another question, I created 2 simple modules that call each other to understand the circular import in python, but this has only generated more confusion for me.

I have the following 2 modules:

# module X.py

print('x1')
def X1():
    return "x1"

from Y import Y2
print('x2')
def X2():
    return "x2"
# module Y.py

print('y1')
def Y1():
    return "y1"
from X import X1

print('y2')
def Y2():
    return "y2"

When I run X.py an error happens:

x1
y1
x1
Traceback (most recent call last):
  File "X.py", line 7, in <module>
    from Y import Y2
  File "***/Y.py", line 6, in <module>
    from X import X1
  File "***/X.py", line 7, in <module>
    from Y import Y2
ImportError: cannot import name 'Y2' from 'Y' (***/Y.py)

When I run Y.py, no error happens, but I don't understand the order of the print.

y1
x1
y1
y2
x2
y2

I use python 3.8.3.

Camilo
  • 39
  • 1
  • 3
  • Does this answer your question? [ImportError: Cannot import name X](https://stackoverflow.com/questions/9252543/importerror-cannot-import-name-x) – pppery Jun 27 '20 at 04:34
  • Although I understand what they answer, it does not agree with what happens to me. When I run X I should run the X code and print 'x1', then I do 'from Y import Y2' so I should run Y and print 'y1', then with 'from X import X1' as X1 was already defined there should be no error, and then 'y2' should be printed, exit module Y and continue on X and print 'x2'. But this is not what happens for me. Maybe I am misunderstanding. – Camilo Jun 27 '20 at 04:49
  • Note that in your traceback `X.py` appears with and without its directory. The outer one is a script, while the inner one is a module (albeit loaded from the same file!). – Davis Herring Jun 27 '20 at 06:40

2 Answers2

2

This answer may help to realize importing process.

I tried to show the sequence of steps while importing in both cases below.

When you run Y.py. the order is:

  • Running Y.py as __main__
  • def Y1() -> define Y1() in __main__
  • from X import X1 -> import and run X.py as X
  • def X1() -> define X1() in X
  • from Y import Y2 -> import and run Y.py as Y
  • def Y1() -> define Y1() in Y
  • from X import X1 -> OK. X.X1 was defined already
  • def Y2() -> define Y2() in Y
  • def X2() -> define X2() in X

And when you run X.py, the order is:

  • Running X.py as __main__
  • def X1() -> define X1() in __main__
  • from Y import Y2 -> import and run Y.py as Y
  • def Y1() -> define Y1() in Y
  • from X import X1 -> import and run X.py as X
  • def X1() -> define X1() in X
  • from Y import Y2 -> ERROR. Y.Y2 was not defined yet
alex_noname
  • 26,459
  • 5
  • 69
  • 86
  • This is a great answer! The important thing is that when I run 'X.py' it runs as `__main__` and not as `X`. Thanks – Camilo Jun 29 '20 at 03:22
1

When you run X.py, it attempts to import Y2 from Y.py. In Y.py, Y2 is defined after from X import X1, which causes the circular dependency.

When you run Y.py, it attempts to import X1 from X.py. In X.py, X1 is defined before from Y import Y2, so there is no circular dependency.

DYZ
  • 55,249
  • 10
  • 64
  • 93