[英]Difference between “import lib.foo” and “import lib.foo as f” in Python
I'm puzzled by how circular imports are handled in Python. 我对Python中循环导入的处理方式感到困惑。 I've tried to distill a minimal question and I don't think this exact variant was asked before.
我试图提炼一个最小的问题,我不认为这个确切的变体之前被问过。 Basically, I'm seeing a difference between
基本上,我看到了两者之间的区别
import lib.foo
and 和
import lib.foo as f
when I have a circular dependency between lib.foo
and lib.bar
. 当我在
lib.foo
和lib.bar
之间有一个循环依赖。 I had expected that both would work the same: the (possibly half-initialized) module would be found in sys.modules
and put into the local namespace. 我原以为两者都是一样的:(可能是半初始化的)模块可以在
sys.modules
找到并放入本地命名空间。 (From testing I noticed that import lib.foo
really puts lib
into the local namespace — okay, with that syntax I'll do lib.foo.something
anyway.) (从测试中我注意到,
import lib.foo
确实将lib
放入本地命名空间 - 好吧,不管怎样,我会用lib.foo.something
做这个语法。)
However, if lib.foo
is already in sys.modules
, then import lib.foo as f
tries to access foo
as an attribute on lib
and raises AttributeError. 但是,如果
lib.foo
已经在sys.modules
,则import lib.foo as f
尝试访问foo
作为lib
上的属性并引发AttributeError。 Why does the behavior (seemingly) depend on the presence in sys.modules
? 为什么行为(貌似)依赖于
sys.modules
的存在?
Also, where is this behavior documented? 此外,这种行为记录在哪里? I don't feel that the Python
import
statement reference explains this behavior, or at least I couldn't extract it :-) 我不觉得Python
import
语句引用解释了这种行为,或者至少我无法解压缩它:-)
All in all I'm trying to change a code base to use the oft recommended style where you import modules, not symbols in the modules: 总而言之,我正在尝试更改代码库以使用经常导入模块的方式,而不是模块中的符号:
from project.package import moduleA
from project.package import moduleB
But that fails when there are circular imports between the two modules. 但是当两个模块之间存在循环导入时,这会失败。 I had expected it to work as long as the top-level definitions in the two modules don't depend on each other (eg, no subclass in
moduleB
with a base class in moduleA
). 我曾期望它能够工作,只要两个模块中的顶级定义不相互依赖(例如,
moduleB
没有基类在moduleA
子类)。
Test script: 测试脚本:
#!/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'
When you say import lib.foo as f
what you are telling Python to do is the equivalent of import lib.foo; f = lib.foo
当你说
import lib.foo as f
,你告诉Python要做的就是import lib.foo; f = lib.foo
import lib.foo; f = lib.foo
at the bytecode level. import lib.foo; f = lib.foo
字节码级别的import lib.foo; f = lib.foo
。 You end up with an AttributeError in the issue being asked because lib
in this case doesn't have foo
set yet as an attribute. 您在被问题的问题中最终会出现AttributeError,因为在这种情况下,
lib
没有将foo
设置为属性。 Python hasn't completed its import of lib.foo
when it tries to do the assignment and thus has not set the attribute yet on lib
; 当
lib.foo
尝试执行赋值时,它还没有完成对lib.foo
导入,因此还没有在lib
上设置属性; look at the Python 3.3 source for import where you can see where a module is loaded vs. couple statements farther down where a module is set on its parent . 查看用于导入的Python 3.3源代码,您可以在其中查看加载模块的位置与在其父级上设置模块的更远的几个语句。
This is where you end up with some circular import issues. 这是您最终遇到一些循环导入问题的地方。 You need to let the import for
lib.foo
complete before you try to access lib.foo
, else the attribute on lib
simply won't exist yet for the bytecode to access. 在尝试访问
lib.foo
之前,需要让lib.foo
的导入完成,否则lib
上的属性根本不存在,以便字节码可以访问。 This might be why you think you are not using any top-level definitions directly in your code but in actuality you are through your import statements. 这可能就是为什么您认为您没有直接在代码中使用任何顶级定义,但实际上您是通过import语句。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.