我有一个具有以下结构的Python项目:
testapp/
??? __init__.py
??? api
? ??? __init__.py
? ??? utils.py
??? utils.py
Run Code Online (Sandbox Code Playgroud)
所有模块都是空的,除了testapp/api/__init__.py它有以下代码:
from testapp import utils
print "a", utils
from testapp.api.utils import x
print "b", utils
Run Code Online (Sandbox Code Playgroud)
和testapp/api/utils.py其限定x:
x = 1
Run Code Online (Sandbox Code Playgroud)
现在从我导入的根目录testapp.api:
$ export PYTHONPATH=$PYTHONPATH:.
$ python -c "import testapp.api"
a <module 'testapp.utils' from 'testapp/utils.pyc'>
b <module 'testapp.api.utils' from 'testapp/api/utils.pyc'>
Run Code Online (Sandbox Code Playgroud)
导入的结果让我感到惊讶,因为它表明第二个import语句已被覆盖utils.然而,文档声明from语句不会绑定模块名称:
from表单不绑定模块名称:它遍历标识符列表,在步骤(1)中找到的模块中查找每个标识符,并将本地名称空间中的名称绑定到找到的对象.
事实上,当我在终端中使用from ... import ...语句时,不会引入任何模块名称:
>>> from os.path import abspath
>>> path
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
Run Code Online (Sandbox Code Playgroud)
我怀疑这与Python有关,在第二次导入语句时,尝试导入testapp.api.utils引用testapp.utils和失败,但我不确定.
这里发生了什么?
use*_*ica 14
从导入系统文档:
当使用任何机制(例如
importlibAPI,import或import-from语句或内置__import__())加载子模块时,绑定将放置在父模块的命名空间中,并放置到子模块对象中.例如,如果包spam具有子模块foo,则在导入之后spam.foo,spam将具有foo绑定到子模块的属性.假设您有以下目录结构:Run Code Online (Sandbox Code Playgroud)spam/ __init__.py foo.py bar.py并
spam/__init__.py在其中包含以下内容:Run Code Online (Sandbox Code Playgroud)from .foo import Foo from .bar import Bar然后执行以下把将名称绑定到
foo与bar所述在spam模块:Run Code Online (Sandbox Code Playgroud)>>> import spam >>> spam.foo <module 'spam.foo' from '/tmp/imports/spam/foo.py'> >>> spam.bar <module 'spam.bar' from '/tmp/imports/spam/bar.py'>鉴于Python熟悉的名称绑定规则,这似乎令人惊讶,但它实际上是导入系统的基本功能.不变控股是,如果你有
sys.modules['spam']和sys.modules['spam.foo'](可能也会上述进口后),后者必须表现为foo前者的属性.
如果这样做from testapp.api.utils import x,import语句将不会加载utils到本地名称空间.但是,导入机制将加载utils到testapp.api命名空间中,以使进一步的导入正常工作.在您的情况下,它恰好testapp.api也是本地命名空间,因此您会感到惊讶.
| 归档时间: |
|
| 查看次数: |
344 次 |
| 最近记录: |