子包中绝对导入失败,因包名与标准库冲突
基本上,我有一个子包,它的名字和标准库的包(“logging”)是一样的。我希望无论我怎么运行它,都能绝对导入标准库的那个包,但当我在父包中时,这个操作失败了。
这看起来像是一个错误,或者是新“绝对导入”支持(从Python 2.5开始)的一种未记录的行为。我在2.5和2.6版本中都试过。
包的结构如下:
foo/
__init__.py
logging/
__init__.py
在 foo/__init__.py
中,我们导入了自己的 logging 子包:
from __future__ import absolute_import
from . import logging as rel_logging
print 'top, relative:', rel_logging
在 foo/logging/__init__.py
中,我们想要导入标准库的 logging
包:
from __future__ import absolute_import
print 'sub, name:', __name__
import logging as abs_logging
print 'sub, absolute:', abs_logging
注意:包含 foo
的文件夹在 sys.path 中。
当从外部或上层导入 foo
时,输出是预期的:
c:\> python -c "import foo"
sub, name: foo.logging
sub, absolute: <module 'logging' from 'c:\python26\lib\logging\__init__.pyc'>
top, relative: <module 'foo.logging' from 'foo\logging\__init__.pyc'>
所以在子包中的绝对导入能够找到标准库的包,正如我们所希望的那样。
但是当我们在 foo
文件夹内时,情况就不同了:
c:\foo>\python25\python -c "import foo"
sub, name: foo.logging
sub, name: logging
sub, absolute: <module 'logging' from 'logging\__init__.pyc'>
sub, absolute: <module 'logging' from 'logging\__init__.pyc'>
top, relative: <module 'foo.logging' from 'c:\foo\logging\__init__.pyc'>
对于“sub, name”的双重输出显示,我自己叫“logging”的子包又导入了一次自己,并且即使“absolute_import”已启用,它也找不到标准库的“logging”包。
我的使用场景是,我希望能够在任何当前目录下都能使用、测试这个包。把名字从“logging”改成其他名字虽然可以解决问题,但这并不是一个理想的办法,而且无论如何,这种行为似乎与绝对导入应该如何工作的描述不符。
有没有人知道这是怎么回事?这是我的错误还是Python的错误?或者这种行为是否在某些文档中有说明?
编辑:gahooa的回答清楚地指出了问题所在。这里展示了一个粗略的解决方法,证明了这个问题:
c:\foo>python -c "import sys; del sys.path[0]; import foo"
sub, name: foo.logging
sub, absolute: <module 'logging' from 'c:\python26\lib\logging\__init__.pyc'>
top, relative: <module 'foo.logging' from 'c:\foo\logging\__init__.pyc'>
1 个回答
sys.path[0]
默认是 ''
,这表示“当前目录”。所以如果你在一个包含 logging
的文件夹里,系统会优先选择这个文件夹。
我最近遇到过这个问题,直到我意识到我其实是在那个文件夹里,sys.path
首先会查看我当前的文件夹,然后才会去标准库里找。