简体   繁体   English

Python中“import lib.foo”和“import lib.foo as f”之间的区别

[英]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.foolib.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM