0

I have found a strange circular reference in my code and here is the minimum code:

ph
|-- mod
|   |-- __init__.py
|   |-- pkg.py  # import mod.sub_mod.sub_pkg
|   `-- sub_mod
|       |-- __init__.py
|       `-- sub_pkg.py  # from mod import pkg
`-- main.py

in mod, only pkg.py and sub_pkg.py have file content.

In main.py:

import mod.pkg

will cause an ImportError, but

import mod.sub_mod.sub_pkg

works well.

when i am trying to find this minimal reproducible example, i found that in python 3, both import will work. I also found this page: https://gist.github.com/datagrok/40bf84d5870c41a77dc6 but i still don't know why.

1

1 Answer 1

1

If you start the circular import with import mod.pkg, then mod/pkg.py starts first, and tries to import mod.sub_mod.sub_pkg. mod/sub_mod/sub_pkg.py starts, and tries to run from mod import pkg, but the mod.pkg module is already being initialized.

Python skips to trying to retrieve the pkg attribute from the mod module object. However, that attribute isn't set until the mod.pkg module finishes initializing, so from mod import pkg fails.


If you start the circular import with import mod.sub_mod.sub_pkg, then mod/sub_mod/sub_pkg.py starts first, and tries to run from mod import pkg. mod/pkg.py starts, and tries to import mod.sub_mod.sub_pkg. The mod.sub_mod.sub_pkg module is already initialized, but Python doesn't try to access attributes this time.

from mod import pkg needs to retrieve the pkg attribute from mod because it needs to bind the value of that attribute to the name pkg in the local namespace. However, import mod.sub_mod.sub_pkg only binds the mod name in the local namespace. Python binds the mod name to the mod module in mod.pkg's module namespace and continues on.


In Python 3, in the first case, there's a fallback when from mod import pkg fails to find the pkg attribute on mod. Python checks the sys.modules dict for an entry for 'mod.pkg', finds one, and binds the module it finds to the pkg name.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.