无法解决“import as”情况(“AttributeError模块x没有属性y”)

7

我有一个以下结构的项目:

project/
    driver.py
    lib/
        __init__.py
        core/
            util.py
            common.py
            __init__.py

# project/driver.py

import lib.core.common as abc
pass

# project/lib/core/__init__.py

from .util import Worker

# project/lib/core/util.py

import lib.core.common as abc

class Worker:
    pass

# project/lib/core/common.py

def stuff():
    pass

现在当我在项目目录下运行python3 driver.py时,我会得到以下错误:

Traceback (most recent call last):
  File "driver.py", line 1, in <module>
    import lib.core.common as abc
  File "/home/user/project/lib/core/__init__.py", line 1, in <module>
    from .util import Worker
  File "/home/user/project/lib/core/util.py", line 1, in <module>
    import lib.core.common as abc
AttributeError: module 'lib' has no attribute 'core'

只有当两个条件都满足时,才会出现这种情况:
1. 当我使用import lib.core.common as abc而不是import lib.core.common时。 2. 当project/lib/core/__init__.py包含from .util import Worker导入时。
问题在于我想保留import lib.core.common as abc的导入形式。请问有人能解释一下这里发生了什么吗?

1
不是直接的答案,但如果你在lib/core/__init__.py中不急切地from .util import Worker,你的问题就会消失。基本上,您有一个依赖循环:lib.core.common -> lib.core.__init__ -> lib.core.util.Worker -> lib.core.common。当定义Worker时,common模块实际上还不存在。为什么需要像那样将Worker引入软件包范围内呢? - Daniel Pryden
1个回答

0

您有循环依赖的导入。您尝试执行

import lib.core.common as abc

在两个文件中,分别是driver.pyutil.py

最简单的解决方法是将路径导入移动到节点模块的末尾some docs,或者

def dostuff():
    from foo import bar
    ...

或者这个也可以工作,

from lib.core import common as abc

当Python导入一个模块时,它会检查模块注册表,以查看该模块是否已经被导入。如果该模块已经被注册,Python将使用缓存中的现有对象。模块注册表是一张表格,其中包含已初始化并按模块名称索引的模块。可以通过sys.modules访问此表。

如果未注册,则Python会查找该模块,必要时进行初始化,并在新模块的命名空间中执行它。


将路径导入移动到节点模块的末尾是什么意思?我能请求一个应用于我的案例的示例吗? - JoaoAlby
@JoaoAlby,我已更新我的答案,你可以在你的两个文件中使用from lib.core import common as abc,这样就可以工作了。 - Druta Ruslan
在文件中间导入是违反PEP8规范的。 - TomSawyer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接