代码之家  ›  专栏  ›  技术社区  ›  Peter Hansen

绝对导入在隐藏stdlib包名称的子包中失败

  •  8
  • Peter Hansen  · 技术社区  · 15 年前

    基本上,我有一个与标准库包同名的子包(“日志”),我希望它能够绝对导入标准包,无论我如何运行它,但当我在父包中时,这会失败。

    它看起来像是一个bug,或者是新的“绝对导入”支持(从Python 2.5开始就是新的)的未记录行为。尝试使用2.5和2.6。

    foo/
        __init__.py
        logging/
            __init__.py
    

    foo/__init__.py 我们导入自己的日志子包:

    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中。


    从外部/上方导入时 ,输出如预期:

    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'>
    

    因此,子包中的绝对导入会根据需要找到stdlib包。

    但是当我们在里面的时候 文件夹,它的行为不同:

    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'>
    

    即使启用了“绝对导入” .

    用例是,我希望能够使用、测试等此包,而不管当前目录是什么。将名称从“logging”更改为其他名称可能是一种解决方法,但不是一种理想的方法,而且在任何情况下,这种行为似乎都不符合绝对导入的工作方式。

    你知道发生了什么吗,这是一个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'>
    
    1 回复  |  直到 15 年前
        1
  •  10
  •   gahooa    15 年前

    sys.path[0] 默认情况下是 '' ,表示“当前目录”。因此,如果你坐在一个目录与 logging 在它里面,那将是首先被选择的。

    sys.path 在查看标准库之前,我首先选择了我当前的目录。