如何从 python3 中的兄弟目录导入?
How to import from a sibling directory in python3?
我有以下文件结构:
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")
I 运行 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()
.
我找到了 and this post, but they start with a file that's quite deep in the file structure (mine is right at the top). I also found this post,但它似乎在谈论一个包而不是一个普通的 .py。
这里的解决方案是什么?
您可以删除这些点,它应该可以工作:
# parsemessages.py
from helpers import parse
parse.execute("string to be parsed")
如果您真的不想将其打包,那可能是您的最佳解决方案。您还可以将整个项目嵌套到更深的一个目录,并将其命名为 python3 foo/bot.py
.
解释:
当您不使用实际安装的包而只是导入与当前工作目录相关的内容时,该目录中的所有内容都被视为顶级包。在您的例子中,bot
、plugins
、helpers
和 commands
都是顶级 packages/modules。您当前的工作目录本身不是一个包。
所以当你做...
from ..helpers import parse
... helpers
被认为是顶级包,因为它在您当前的工作目录中,并且您正试图从比它更高的级别导入 (from 你当前的工作目录本身,它不是一个包。
当你做...
from .helpers import parse
...您正在导入相对于 plugins
。所以 .helpers
解析为 plugins.helpers
.
当你做...
from helpers import parse
...它发现 helpers
是顶级包,因为它在您当前的工作目录中。
如果您想从根目录执行代码,我对此的最佳回答是使用 os.getcwd() 添加到您的根文件夹的路径。
确保你的兄弟文件夹有一个 init.py 文件。
import os
os.sys.path.insert(0, os.getcwd())
from sibling import module
我有以下文件结构:
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")
I 运行 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()
.
我找到了
这里的解决方案是什么?
您可以删除这些点,它应该可以工作:
# parsemessages.py
from helpers import parse
parse.execute("string to be parsed")
如果您真的不想将其打包,那可能是您的最佳解决方案。您还可以将整个项目嵌套到更深的一个目录,并将其命名为 python3 foo/bot.py
.
解释:
当您不使用实际安装的包而只是导入与当前工作目录相关的内容时,该目录中的所有内容都被视为顶级包。在您的例子中,bot
、plugins
、helpers
和 commands
都是顶级 packages/modules。您当前的工作目录本身不是一个包。
所以当你做...
from ..helpers import parse
... helpers
被认为是顶级包,因为它在您当前的工作目录中,并且您正试图从比它更高的级别导入 (from 你当前的工作目录本身,它不是一个包。
当你做...
from .helpers import parse
...您正在导入相对于 plugins
。所以 .helpers
解析为 plugins.helpers
.
当你做...
from helpers import parse
...它发现 helpers
是顶级包,因为它在您当前的工作目录中。
如果您想从根目录执行代码,我对此的最佳回答是使用 os.getcwd() 添加到您的根文件夹的路径。 确保你的兄弟文件夹有一个 init.py 文件。
import os
os.sys.path.insert(0, os.getcwd())
from sibling import module