我对Python中如何处理循环导入感到困惑。我试图提炼出一个最简问题,我不认为之前有人问过这个确切的变体。基本上,我看到了一个区别:
import lib.foo
并且
import lib.foo as f
当我在
lib.foo
和lib.bar
之间存在循环依赖时。我原本以为两者的工作方式相同:可能只初始化了一半的模块将被找到并放入本地命名空间中。sys.modules
中可以找到它。 (从测试中我发现import lib.foo
确实将lib
放入本地命名空间 - 好吧,用那个语法我仍然会做lib.foo.something
。)
然而,如果lib.foo
已经在sys.modules
中,则import lib.foo as f
尝试访问lib
上的foo
属性并引发AttributeError。为什么这种行为(表面上)取决于在sys.modules
中的存在?
此外,这种行为在哪里有记录?我感觉Python import
statement reference没有解释这种行为,或者至少我无法提取出来 :-)
总之,我正在尝试更改代码库以使用oft recommended风格,在该风格中,您导入模块而不是模块中的符号:
from project.package import moduleA
from project.package import moduleB
但是当两个模块之间存在循环依赖时,这种方法就会失败。我曾期望只要两个模块中的顶层定义不相互依赖(例如,在moduleB中没有以moduleA中的基类为基类的子类),它就能够正常工作。
测试脚本:
#!/bin/sh
rm -r lib; mkdir lib
touch lib/__init__.py
cat > lib/foo.py <<EOF
# lib.foo module
print '{ foo'
#import lib.bar # works
import lib.bar as b # also works
#from lib import bar # also works
print 'foo }'
EOF
cat > lib/bar.py <<EOF
# lib.bar module
print '{ bar'
#import lib.foo # works
import lib.foo as f # AttributeError: 'module' object has no attribute 'foo'
#from lib import foo # ImportError: cannot import name foo
print 'bar }'
EOF
python -c 'import lib.foo'