如何创建始终有效的导入?

2024-06-01

我正在努力在我的一个项目中建立一个工作结构。问题是,我有一个像这样的结构的主包和子包(我遗漏了所有不必要的文件):

code.py
mypackage/__init__.py
mypackage/work.py
mypackage/utils.py

utils.py 有一些实用程序代码,通常仅在 mypackage 包中使用。

我通常在每个模块文件中都有一些测试代码,它们调用当前模块的一些方法并打印一些内容以快速检查一切是否正常工作。这段代码被放置在if __name__ == "__main__"块位于文件末尾。所以我直接通过包含 utils.pyimport utils。例如 mypackage/work.py 看起来像:

import utils

def someMethod():
    pass

if __name__ == "__main__":
    print(someMethod())

但是现在当我在父包(例如 code.py)中使用这个模块时,我像这样导入它

import mypackage.work

我收到以下错误:

ImportError: No module named 'utils'

经过一番研究后我发现,这可以通过添加来解决mypackage/文件夹到 PYTHONPATH 环境变量,但这对我来说感觉很奇怪。难道就没有其他方法可以解决这个问题吗?我听说过相对进口,但这在关于模块的 python 文档 https://docs.python.org/3.5/tutorial/modules.html

请注意,相对导入基于当前模块的名称。由于主模块的名称始终是“main",用作 Python 应用程序主模块的模块必须始终使用绝对导入。

有什么建议我可以如何拥有if __name__ == "__main__"子模块中的部分,并且还可以使用父包中的此文件而不会弄乱导入?

EDIT:如果我使用相对导入work.py正如 import utils 的答案中所建议的:

from . import utils

我收到以下错误:

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

不幸的是,相对导入和子模块的直接运行不能混合。

添加父目录mypackage给你的PYTHONPATH或总是cd当你想运行子模块时进入父目录。

那么你有两种可能性:

使用绝对值 (from mypackage import utils) 而不是相对导入 (from . import utils)并像以前一样直接运行它们。该解决方案的缺点是您始终需要编写完全限定的路径,从而使重命名变得更加困难mypackage后来,除其他外。

or

Run python3 -m mypackage.utils等等来运行你的子模块而不是运行python3 mypackage/utils.py.

这可能需要一些时间来适应,但这是更正确的方法(包中的模块与独立脚本不同),并且您可以继续使用相对导入。

还有更多“神奇”的解决方案,涉及__package__ and sys.path但它们都需要在每个文件的顶部添加额外的代码,并包含您想要直接运行的相对导入。我不会推荐这些。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何创建始终有效的导入? 的相关文章

随机推荐