Mar*_*ler 9 python module circular-dependency python-import
我对Python中循环导入的处理方式感到困惑.我试图提炼一个最小的问题,我不认为这个确切的变体之前被问过.基本上,我看到了两者之间的区别
import lib.foo
Run Code Online (Sandbox Code Playgroud)
和
import lib.foo as f
Run Code Online (Sandbox Code Playgroud)
当我lib.foo和之间有一个循环依赖lib.bar.我曾预料到两者都会起作用:(可能是半初始化的)模块可以在sys.modules本地命名空间中找到并放入本地命名空间.(从测试中我注意到它import lib.foo确实放入lib了本地命名空间 - 好吧,lib.foo.something无论如何我会用这种语法.)
但是,如果lib.foo已经存在sys.modules,则import lib.foo as f尝试foo作为属性访问lib并引发AttributeError.为什么行为(看似)依赖于存在sys.modules?
此外,这种行为记录在哪里?我不觉得Python import语句引用解释了这种行为,或者至少我无法解压缩它:-)
总而言之,我正在尝试更改代码库以使用经常导入模块的方式,而不是模块中的符号:
from project.package import moduleA
from project.package import moduleB
Run Code Online (Sandbox Code Playgroud)
但是当两个模块之间存在循环导入时,这会失败.我曾期望它能够工作,只要两个模块中的顶级定义不相互依赖(例如,没有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'
Run Code Online (Sandbox Code Playgroud)
当你说import lib.foo as f你告诉Python要做的事情就是import lib.foo; f = lib.foo字节码级别的等价物.您在被询问的问题中最终会出现AttributeError,因为lib在这种情况下,尚未将fooset设置为属性.Python lib.foo在尝试执行赋值时尚未完成导入,因此尚未设置该属性lib; 查看用于导入的Python 3.3源代码,您可以在其中查看加载模块的位置,以及在其父级上设置模块的更远的几个语句.
这是您最终遇到一些循环导入问题的地方.lib.foo在尝试访问之前,您需要让导入完成lib.foo,否则lib对于要访问的字节码,该属性根本不存在.这可能就是为什么您认为您没有直接在代码中使用任何顶级定义,但实际上您是通过import语句.
| 归档时间: |
|
| 查看次数: |
577 次 |
| 最近记录: |