另一个绝对导入问题

5 投票
2 回答
3785 浏览
提问于 2025-04-15 13:32

我在使用自己的模块时遇到了问题,它们覆盖了Python自带的模块(特别是日志模块)。这是我的项目结构:

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

run.py

from package import main

main()

package/__init__.py

from __future__ import absolute_import
import logging
import logging.config

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

package/logging/__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的发布说明,发现绝对导入其实挺简单的。不过,我还是没能搞明白这个问题出在哪里。

我漏掉了什么呢?

2 个回答

1

你可以使用相对导入来指定Python首先在哪里查找模块:

在包的__init__.py文件中

from . import logging
9

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

发生的情况是,当你导入一个包中的模块时,这个模块会自动被添加到这个包的命名空间里。所以

from package.logging import Logging

不仅会把 'Logging' 加入到包的 _dict 中,还会把 'logging'(新导入的本地模块)也加入到包的 _dict 中。这样一来,你首先导入了 logging(顶层模块),它可以通过 package.logging 来访问,然后你又用本地模块覆盖了这个变量。这基本上意味着,你不能像预期那样同时通过 package.logging 来访问顶层模块和你的本地模块。

在这个特定的情况下,你可能并不想把顶层的 logging 模块作为公共名称“导出”。相反,你可以这样做:

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

撰写回答