我已经回答了有关Python中绝对导入的问题,我认为通过阅读Python 2.5 changelog和随附的PEP可以理解。但是,在安装Python 2.5并尝试制作一个正确使用的示例时from __future__ import absolute_import
,我意识到事情还不清楚。
直接从上面链接的更改日志,此语句准确总结了我对绝对导入更改的理解:
假设您有一个像这样的包目录:
pkg/ pkg/__init__.py pkg/main.py pkg/string.py
这定义了一个名为的包,
pkg
其中包含pkg.main
和pkg.string
子模块。考虑main.py模块中的代码。如果执行该语句会
import string
怎样?在Python 2.4和更早的版本,它会先看看在包的目录进行相对进口,发现包装/ string.py,进口该文件的内容pkg.string
模块,并且该模块被绑定到名字"string"
的pkg.main
模块的名称空间。
所以我创建了这个确切的目录结构:
$ ls -R
.:
pkg/
./pkg:
__init__.py main.py string.py
__init__.py
并且string.py
是空的。main.py
包含以下代码:
import string
print string.ascii_uppercase
不出所料,使用Python 2.5运行此命令失败,并显示AttributeError
:
$ python2.5 pkg/main.py
Traceback (most recent call last):
File "pkg/main.py", line 2, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
但是,在2.5更新日志中,我们发现了这一点(添加了重点):
在Python 2.5中,您可以
import
使用from __future__ import absolute_import
指令将的行为切换为绝对导入。在将来的版本(可能是Python 2.7)中,此绝对导入行为将成为默认设置。一旦将绝对导入设置为默认设置,import string
就将始终找到标准库的版本。
因此pkg/main2.py
,我创建了,main.py
但与将来的import指令相同。现在看起来像这样:
from __future__ import absolute_import
import string
print string.ascii_uppercase
但是,使用Python 2.5运行它会失败AttributeError
:
$ python2.5 pkg/main2.py
Traceback (most recent call last):
File "pkg/main2.py", line 3, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
这个漂亮的断然反驳该语句import string
将始终找到STD-库版本绝对进口启用。而且,尽管警告了绝对导入已计划成为“新的默认”行为,但无论使用还是不使用__future__
指令,我都使用Python 2.7遇到了相同的问题:
$ python2.7 pkg/main.py
Traceback (most recent call last):
File "pkg/main.py", line 2, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
$ python2.7 pkg/main2.py
Traceback (most recent call last):
File "pkg/main2.py", line 3, in <module>
print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'
以及Python 3.5(有无)(假设print
两个文件中的语句均已更改):
$ python3.5 pkg/main.py
Traceback (most recent call last):
File "pkg/main.py", line 2, in <module>
print(string.ascii_uppercase)
AttributeError: module 'string' has no attribute 'ascii_uppercase'
$ python3.5 pkg/main2.py
Traceback (most recent call last):
File "pkg/main2.py", line 3, in <module>
print(string.ascii_uppercase)
AttributeError: module 'string' has no attribute 'ascii_uppercase'
我已经测试了其他变化。相反的string.py
,我已经创建了一个空的模块-一个新的目录string
仅包含一个空的__init__.py
-而不是从发放的进口main.py
,我有cd
“d到pkg
并直接从REPL运行的进口。这些变体(或它们的组合)都没有改变上面的结果。我无法将其与我已阅读的有关__future__
指令和绝对导入的内容相协调。
在我看来,这很容易通过以下方式进行解释(这是来自Python 2文档,但该语句在适用于Python 3的同一文档中保持不变):
系统路径
(...)
在程序启动时进行初始化,该列表的第一项
path[0]
是包含用于调用Python解释器的脚本的目录。如果脚本目录不可用(例如,如果解释器是交互式调用的,或者从标准输入中读取了脚本),path[0]
则为空字符串,该字符串将Python首先引导到当前目录中的搜索模块。
那我想念什么呢?为什么该__future__
声明似乎不按其要求行事?在文档的这两部分之间以及所描述的行为与实际行为之间,这种矛盾的解决方案是什么?