【问题标题】:Another absolute import problem另一个绝对导入问题
【发布时间】:2009-08-11 23:10:06
【问题描述】:

我自己的模块覆盖 Python 内置模块(特别是日志记录模块)时遇到问题。这是我的项目布局:

run.py
package/
        __init__.py
        logging/
                __init__.py
        ...

运行.py

from package import main

main()

包/__init__.py

from __future__ import absolute_import
import logging
import logging.config

def main():
    logging.config.fileConfig(...)

包/日志/__init__.py

class Logging(object):
    pass

就目前而言,上述代码有效。一旦我尝试从 package.logging 导入 Logging 类,如下所示:

from __future__ import absolute_import

import logging
import logging.config
from package.logging import Logging

def main():
    logging.config.fileConfig(...)

我收到一个错误:

AttributeError: 'module' object has no attribute 'config'

我已阅读PEP 328 发行说明,发现绝对导入相当简单。不幸的是,我无法弄清楚这一点。

我在这里错过了什么?

【问题讨论】:

    标签: python


    【解决方案1】:

    相对和绝对导入 (PEP 328) 不是这里的问题。

    当一个包中的一个模块被导入时,它会被隐式地添加到这个包的命名空间中。所以

    from package.logging import Logging
    

    不仅在 package._dict_ 中添加了“Logging”,还在 package._dict_ 中添加了“logging”(新导入的本地模块)。因此,您首先导入日志记录(顶级模块),它可以作为 package.logging 使用,然后用本地模块覆盖此变量。这基本上意味着您不能像预期的那样使用 package.logging 来访问顶级模块和本地模块。

    在这种特定情况下,您可能不想将顶级日志记录模块“导出”为公共名称。而是这样做:

    from logging import config as _config
    def main():
        _config.fileConfig(...)
    

    【讨论】:

    • 哇,刚刚学会了一个新的 Python 陷阱。我需要自己测试一下,就像你说的那样。如果其他人想验证这一点,只需在from package.logging import Logging 之后添加print logging
    【解决方案2】:

    您可以使用relative imports 强制python首先在哪里查找模块:

    in package/__init__.py

    from . import logging
    

    【讨论】:

    • 使用您的示例似乎确实有效。但是,我现在必须将 Logging 类称为 logging.Logging。进一步的测试表明,“from .logging import Logging”似乎不像 PEP 328 建议的那样工作。我仍然不明白为什么“from package.logging import Logging”不起作用。这不是绝对的进口吗?
    • 你用的是什么版本的python?如果它是旧版本(比如 2.4),则相对导入可能无法正常工作,或者至少不能按预期工作。
    • 我刚刚验证了这个问题也会影响 Python 2.5.2
    猜你喜欢
    • 1970-01-01
    • 2014-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-25
    • 2016-10-13
    相关资源
    最近更新 更多