After some search, I figure out the answer myself.
Essentially, circular import is a problem for from … import …
because it returns the imported module only after the module code is executed.
To illustrate, assume we have import a in b.py and import b in a.py. For import a
and import b
, I simply look up sys.modules to find a/b, just put a new module in and return.
On the other hand, from a import c
in b.py has code like this (pseudo python, similar for from b import d
in a.py)
if 'a' not in sys.modules:
sys.modules[a] = (A new empty module object)
run every line of code in a.py
add the module a to its parent's namespace
return module 'a'
we start from a.py, put an empty module for b to sys.modules and start executing b.py and put a in sys.modules and executing a.py. Next it hits from b import d
again and find the b in sys.modules but it's empty, throws error: no attribute d.
PS1: the referred post is wrong. import ... as ...
is good for circular import.
PS2: from a import c
is the same to import a.c in python 3