gpt4 book ai didi

python - 模块从相关文件夹导入并定期执行

转载 作者:行者123 更新时间:2023-11-28 22:54:13 25 4
gpt4 key购买 nike

假设我有以下结构:

app/
__init__.py
mod.py

pkg/
__init__.py
submod.py

模块 submod 相对于 mod 的导入,即:

from .. import mod

我知道如果我想将 submod 作为脚本执行,我可以从 app/

执行以下操作
python -m pkg.submod

但我希望 submod.py 成为一个可执行模块,我可以使用

系统中的任何地方调用它

python/path/to/submod.py

我认为 PEP-366修复了这个问题,即我认为在 submod 中进行任何相关导入之前添加以下样板代码:

if __name__ == "__main__" and __package__ is None:
__package__ = "app.pkg"

然后我可以返回到常规 python/path/to/submod.py。但是,当我这样做时,我得到:

SystemError: Parent module 'app' not loaded, cannot perform relative import

为什么?

最后我了解到一种解决方案是在 submod 中操作 sys.path 以便它可以看到 mod1 然后执行常规 import mod1 并避免相对导入。 但是作为this question显示,这是危险的,因为一个模块中对 sys.path 的任何更改都会传播到其他所有内容,因此通常篡改 sys.path 不是一个好主意。

有什么办法可以:

  • 相对导入,支持常规 python/path/to/submod.py 调用

  • 能够使用 python/path/to/submod.py 执行我的模块,而无需篡改 sys.pathPYTHONPATH

?

最佳答案

正如 PEP 366 在您复制的样板文件之后明确指出的那样:

Note that this boilerplate is sufficient only if the top level package is already accessible via sys.path. Additional code that manipulates sys.path would be needed in order for direct execution to work without the top level package already being importable.

因此,假设您的代码如下所示:

if __name__ == "__main__" and __package__ is None:
__package__ = "app.pkg"
from .. import mod

你应该得到这样的异常:

SystemError: Parent module 'app' not loaded, cannot perform relative import

如错误消息所示,您需要以某种方式导入 app,然后才能执行任何相关导入。这显然意味着您不能相对导入 app,因此您需要绝对导入它。您可以通过各种 hacky 方法来执行此操作,或者您可以按照 PEP 的建议进行操作,并使用 sys.path 处理所有暗示的问题。但除此之外,你不能这样做。


这只是尝试从包中间运行脚本很困难的多个原因之一。那是故意的;如 PEP 3122 中所述:

Guido views running scripts within a package as an anti-pattern.

有两种方法可以完成您想要的。首先,您已经开始工作:只需将模块作为模块而不是脚本来运行。 (让这项工作成为 PEP 366 的主要目的。)另一个是将模块和脚本分成两部分。您只需编写包装器即可轻松完成。

例如,假设 submod.py 看起来像这个愚蠢的玩具示例:

if __name__ == "__main__" and __package__ is None:
__package__ = "app.pkg"
from .. import mod

def main(argv):
print(argv)

if __name__ == '__main__':
import sys
main(sys.argv)

创建一个新文件,比如 sub.py,作为包的同级文件:

import sys
import app.pkg.submod
app.pkg.submod.main(sys.argv)

现在,您可以从系统的任何位置运行 sub.py。作为sys.path说:

As initialized upon program startup, the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter.

因为那个目录也是 app 所在的目录,你保证能够绝对导入 app.pkg.submod,这意味着 submod 将能够相对导入它想要的任何内容。

关于python - 模块从相关文件夹导入并定期执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18323211/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com