基本上我有一个与标准库包相同名称的子包("logging"),我希望它能够绝对导入标准库,无论我如何运行它,但是当我进入时它会失败父包.
它看起来像是一个bug,或者是新的"绝对导入"支持的无证行为(Python 2.5中的新版本).试过2.5和2.6.
包装布局:
foo/
__init__.py
logging/
__init__.py
Run Code Online (Sandbox Code Playgroud)
在foo/__init__.py我们导入我们自己的日志子包:
from __future__ import absolute_import
from . import logging as rel_logging
print 'top, relative:', rel_logging
Run Code Online (Sandbox Code Playgroud)
在foo/logging/__init__.py我们要导入stdlib logging包:
from __future__ import absolute_import
print 'sub, name:', __name__
import logging as abs_logging
print 'sub, absolute:', abs_logging
Run Code Online (Sandbox Code Playgroud)
注意:包含的文件夹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'>
Run Code Online (Sandbox Code Playgroud)
因此,子包中的绝对导入会根据需要找到stdlib包.
但是当我们进入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'>
Run Code Online (Sandbox Code Playgroud)
对于"子,名"双输出表明,我自己的子包称为"记录"是进口本身是第二次,它没有找到STDLIB"日志"包即使"absolute_import"已启用.
用例是我希望无论当前目录是什么,我都能够使用,测试等.将名称从"日志记录"更改为其他名称将是一种解决方法,但不是理想的,并且在任何情况下,此行为似乎都不符合绝对导入应如何工作的描述.
任何想法发生了什么,这是一个bug(我的或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'>
Run Code Online (Sandbox Code Playgroud)
gah*_*ooa 10
sys.path[0]默认情况下'',这意味着"当前目录".因此,如果您坐在其中的目录logging中,将首先选择该目录.
我最近遇到了这个问题,直到我意识到我实际上正坐在那个目录中,并且sys.path在查看标准库之前,它正在获取当前目录FIRST.