Python 级别导入示例代码无法工作

13 投票
1 回答
20026 浏览
提问于 2025-04-17 12:14

我有一些示例文件,按照PEP 328中给出的例子来布局。

moduleX.py 文件的内容是:

from .moduleY import spam
from .moduleY import spam as ham
from . import moduleY
from ..subpackage1 import moduleY
from ..subpackage2.moduleZ import eggs
from ..moduleA import foo
from ...package import bar
from ...sys import path

当我尝试把这个文件当作顶层模块运行时,我遇到了一个异常:

C:\package\subpackage1> python moduleX.py
Traceback (most recent call last):
  File "moduleX.py", line 1, in <module>
    from .moduleY import spam
ValueError: Attempted relative import in non-package

为什么这段代码不工作呢?每个目录里都有__init__.py文件;难道这不应该让它们作为包正常工作吗?

1 个回答

24

根据文档:

你可以看到:

相对导入使用模块的 name 属性来确定该模块在包层次结构中的位置。如果模块的名称不包含任何包的信息(例如,它被设置为 'main'),那么相对导入会被解析为顶层模块,无论该模块在文件系统中的实际位置在哪里。

当你用 python moduleX.py 运行时,你正是在做上面说的事情。相反,试试这个:

python -m package.subpackage1.moduleX

这将导入 moduleX,并将顶层设置为包。从层次结构的顶部运行:

package/
    __init__.py
    subpackage1/
        __init__.py
        moduleX.py
        moduleY.py
    subpackage2/
        __init__.py
        moduleZ.py
    moduleA.py

也就是说,在你的情况下,直接从 c:\ 开始:

cd c:\
python -m package.subpackage1.moduleX

注意一件事 - 在 moduleX.py 中的导入是这些:

from .moduleY import spam
from .moduleY import spam as ham
from . import moduleY
from ..subpackage1 import moduleY
from ..subpackage2.moduleZ import eggs
from ..moduleA import foo
from ...package import bar
from ...sys import path

倒数第二个:

from ...package import bar

需要根文件夹(在你的情况下是 c:\)是一个包(也就是说,必须有 __init__.py 文件)。此外,它还需要在 package\__init__.py 中定义的 bar 变量,而目前这个变量是不存在的(所以为了测试,把 bar = 'bar!' 放在那里)。它还要求你要在上一级目录 - 所以你必须把 package 文件夹放在另一个文件夹中(这样你就会得到 c:\toppackage\package),然后运行 c:\python -m toppackage.package.subpackage1.moduleX

对于这一行:

from ...sys import path

在上面的 PEP 328 链接中有一个说明:

注意,虽然最后这种情况是合法的,但确实不推荐使用(Guido 用的词是“疯狂”)。

还可以查看其他 Stack Overflow 上的问题,这些问题可能会对你有所帮助:

撰写回答