如何使这些相对导入在Python 3中有效?

2 投票
1 回答
3894 浏览
提问于 2025-04-15 15:08

我有一个这样的文件夹结构:

project/
        __init__.py
        foo/
            __init.py__
            first.py
            second.py
            third.py
        plum.py

project/foo/__init__.py 文件里,我从 first.pysecond.pythird.py 导入了一些类,并把它们放进了 __all__ 里。

first.py 里,有一个叫 WonderfulThing 的类,我想在 second.py 里使用它,并希望通过从 foo 导入 * 来实现。(这里不讨论我为什么想这么做,假设我有正当理由。)

second.py 中,我尝试了 from .foo import *from foo import *from . import *,但这些都没有成功导入 WonderfulThing。我还试过 from ..foo import *,结果出现了一个错误:“尝试进行超出顶层包的相对导入”。

我看过文档和PEP,但还是搞不清楚怎么才能让这个工作。任何帮助都会很感激。

补充说明/编辑:看起来我可能误解了 __all__ 在包中的用法。我一直把它当作在模块中使用,

from .first import WonderfulThing
__all__ = [ "WonderfulThing" ]

但再看看文档似乎表明,__all__ 可能只能在包中用来指定默认导入的模块名称;似乎没有办法包含不是模块的东西。

这样理解对吗?

一个非通配符的导入失败了(cannot import name WonderfulThing)。尝试 from . import foo 也失败了,但 import foo 是可以的。不幸的是,dir(foo) 显示什么都没有。

1 个回答

3

编辑:我确实误解了问题:__all__ 并不只是限制在模块上。

一个问题是你为什么想要使用相对导入。这里使用 from project.foo import * 是完全没问题的。其次,foo 上的 __all__ 限制并不会阻止你使用 from project.foo.first import WonderfulThing,或者直接使用 from .first import WonderfulThing,这仍然是最好的方法。

如果你真的想导入很多东西,最好的办法可能是先用 from project import foo,然后用 foo.WonderfulThing 来使用这些东西,而不是直接用 import * 然后直接使用 WonderfulThing

不过,针对你的直接问题,要从第二个文件 second.py__init__ 文件中导入,你可以这样做:

from . import WonderfulThing

或者

from . import *

撰写回答