如何在Python3中从兄弟目录导入?

10

我有以下文件结构:

bot
├── LICENSE.md
├── README.md
├── bot.py # <-- file that is executed from command line
├── plugins
│   ├── __init__.py
│   ├── debug.py
│   └── parsemessages.py
├── helpers
│   ├── __init__.py
│   ├── parse.py
│   └── greetings.py
└── commands
    ├── __init__.py
    └── search.py

bot.py当从命令行执行时,将会加载plugins目录中的所有内容。

我希望plugins/parsemessages.py能够从helpers目录导入parse,因此我这样做:

# parsemessages.py
from ..helpers import parse
parse.execute("string to be parsed")

我在命令行中运行python3 bot.py

我得到以下错误:

File "/home/bot/plugins/parsemessages.py", line 2, in <module>
  from ..helpers import parse
ValueError: attempted relative import beyond top-level package

所以我把两个点改成了一个:

# parsemessages.py
from .helpers import parse
parse.execute("string to be parsed")

...但我遇到了另一个错误:

File "/home/bot/plugins/parsemessages.py", line 2, in <module>
  from .helpers import parse
ImportError: No module named 'plugins.helpers'

如何让这个导入工作?

值得注意的是,我不打算在这里制作一个包,这只是一个普通的脚本。话虽如此,我不想折腾sys.path - 我希望这样使用很干净。

另外,我想要将parse作为parse导入 - 所以对于上面的示例,我应该输入parse.execute()而不是execute()

我找到了这篇文章这篇文章,但它们都从文件开始,而我的文件结构非常深(我的文件位于顶部)。我还发现了这篇文章,但它似乎在谈论一个包,而不仅仅是一个常规的.py文件。

这里的解决方案是什么?


1
from . import foo? - hd1
如果在您的顶级目录中放置一个__init__.py文件,它是否有效? - jnrbsn
@hd1:from . import parse 导致 ImportError: 无法导入名称 'parse' - snazzybouche
@jnrbsn:遗憾的是,它并没有。 - snazzybouche
https://dev59.com/Im015IYBdhLWcg3w6QA0#50193944 是答案。 - wim
2个回答

6
你可以移除这些点,然后它应该能够正常工作:
# parsemessages.py
from helpers import parse
parse.execute("string to be parsed")

如果您真的不想将其制作成包,那么这可能是最佳解决方案。您也可以将整个项目嵌套在一个目录中并像这样调用它:python3 foo/bot.py

Explanation:

当您没有实际安装软件包但仍要相对于当前工作目录导入内容时,该目录中的所有内容都被视为顶级包。在您的情况下,botpluginshelperscommands都是顶级包/模块。您当前的工作目录本身并不是一个包

所以当你执行...

from ..helpers import parse

“helpers” 被认为是一个顶级包,因为它在你的当前工作目录中,并且你试图从比当前工作目录更高一级的地方导入 ( 当前工作目录 本身,这不是一个包)。

当你执行...

from .helpers import parse

如果你是相对于plugins导入模块,那么.helpers将解析为plugins.helpers

当你执行...

from helpers import parse

如果你的当前工作目录中存在 helpers 文件夹,那么它会被作为顶层包进行查找。


1
如果您想从根目录执行代码,我最好的答案是使用os.getcwd()将您的根文件夹添加到Path中。确保您的兄弟文件夹有一个__init__.py文件。
import os
os.sys.path.insert(0, os.getcwd())

from sibling import module

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