Python - 相对导入

4
我正在开发一个Python程序,它可以管理和运行模块(.py Python文件),用户可以添加模块,并通过使用import函数将其导入到主程序(foo.py)中。以下是目录结构:
Foo/
    foo.py #Main script. Imports ouput.py, core.py and bar.py when needed.
    src/
        __init__.py
        output.py #Output functions required by bar.py and foo.py
        core.py
    modules/
        __init__.py
        bar.py #Needs output.py

我可以使用以下方式在foo.py中导入:

from src.output import *

但我面临的问题是,当我尝试使用以下代码从bar.py中导入output.py时:
from ..src.output import *

我遇到了错误

ValueError: Attempted relative import beyond toplevel package

我将文件放在不同的目录中,因为这样可以让不同的程序员分别编写代码。我肯定需要一个名为“modules”或其他名称的文件夹,在其中可以添加.py模块文件并在bar.py中使用其功能。
请告诉我如果我做错了。如果您有更好的建议,请随时提出。
谢谢。

导入都是相对于顶层的。src.output 在 Foo/src/output 中查找。..src.output 尝试向上跳出 Foo,此时库会崩溃,因为它无法在项目外部进行导入。您应该将要使用的模块添加到其他目录结构中或更改类路径。 - Slater Victoroff
啊,我明白了。当我从foo.bar导入时,不需要加点号。谢谢。但是有没有更好的方法来做这件事? - Grim Reaper
1个回答

4
问题出在Foo没有__init__.py文件,因此它不被视为一个包。
相对导入中的每个点号都代表一个包。例如:当您执行以下操作时,
from ..src.output import *

bar.py 文件中,第一个句点指的是当前包,modules。第二个句点指的是上一级包,Foo。由于 Foo 实际上不是一个包,所以你会得到一个错误。
附注:通配符导入是不被赞同的。特别是当你从远相关的包中导入时,尝试将其重构为显式导入。

谢谢。但是您能否更清楚地解释显式导入?可以举个例子吗? - Grim Reaper
@GrimReaper 显式导入意味着你不应该使用 import *,而是明确声明你要导入的内容,例如 from mymodule import myfunc, myclass - behzad.nouri
谢谢。我的目录结构是否需要进行修改? - Grim Reaper
那么,给 Foo 一个 __init__.py 文件以使相对导入工作(即使它实际上不是一个包)是否有错呢? - martineau

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