CpILL CpILL - 1 year ago 127
Python Question

Python circular importing?

So i'm getting this error

Traceback (most recent call last):
File "/Users/alex/dev/runswift/utils/sim2014/simulator.py", line 3, in <module>
from world import World
File "/Users/alex/dev/runswift/utils/sim2014/world.py", line 2, in <module>
from entities.field import Field
File "/Users/alex/dev/runswift/utils/sim2014/entities/field.py", line 2, in <module>
from entities.goal import Goal
File "/Users/alex/dev/runswift/utils/sim2014/entities/goal.py", line 2, in <module>
from entities.post import Post
File "/Users/alex/dev/runswift/utils/sim2014/entities/post.py", line 4, in <module>
from physics import PostBody
File "/Users/alex/dev/runswift/utils/sim2014/physics.py", line 21, in <module>
from entities.post import Post
ImportError: cannot import name Post

and you can see that i use the same import statement further up and it works? Is there some unwritten rule about circular importing? How do i use the same class further down the call stack?

Answer Source

When you import a module (or a member of it) for the first time, the code inside the module is executed sequentially like any other code; e.g., it is not treated any differently that the body of a function. An import is just a command like any other (assignment, a function call, def, class). Assuming your imports occur at the top of the script, then here's what's happening:

  • When you try to import World from world, the world script gets executed.
  • The world script imports Field, which causes the entities.field script to get executed.
  • This process continues until you reach the entities.post script because you tried to import Post
  • The entities.post script causes physics module to be executed because it tries to import PostBody
  • Finally, physics tries to import Post from entities.post
  • I'm not sure whether the entities.post module exists in memory yet, but it really doesn't matter. Either the module is not in memory, or the module doesn't yet have a Post member because it hasn't finished executing to define Post
  • Either way, an error occurs because Post is not there to be imported

So no, it's not "working further up in the call stack". This is a stack trace of where the error occurred, which means it errored out trying to import Post in that class. You should never use circular imports in Python. It's just asking for trouble. Refactor your module organization.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download