首页 > 解决方案 > 如何在 Python3 中通过 if __name__='__main__' 块使用相对导入?

问题描述

我正在制作一个包,这个包中的模块在if __name__=='__main__':块内有代码用于测试目的。但是我尝试在这些模块中使用相对导入会导致错误。

我已经阅读了这个帖子和其他十亿个帖子:第 10 亿次相对进口

在将其标记为重复之前,如果我想做的事情在 Python3 中是不可能的,那么我的问题是为什么它在 Python2 中有效,以及是什么促使决定在 Python3 中做出如此麻烦的决定?


这是我的示例 Python 项目:

mypackage
- module1.py
- module2.py
- __init__.py

__init__.py并且module2.py是空的

module1.py包含:

import module2

# module1 contents

if __name__=="__main__":
    # Some test cases for the contents of this module
    pass

这在 Python2 中运行良好。我可以从我计算机上任何地方的其他项目导入 module1,我还可以直接运行 module1 并if运行块中的代码。

但是,这种结构在 Python3 中不起作用。如果我尝试在其他地方导入模块,它会失败:

>>> from mypackage import module1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\_MyFiles\Programming\Python Modules\mypackage\module1.py", line 1, in <module>
    import module2
ModuleNotFoundError: No module named 'module2'

所以我尝试将第一行更改为from . import module2, 并修复它,以便我可以从任何地方成功导入模块。但是当我尝试直接将 module1 作为脚本运行时,我得到了这个错误:

Traceback (most recent call last):
  File "C:/_MyFiles/Programming/Python Modules/mypackage/module1.py", line 1, in <module>
    from . import module2
ImportError: cannot import name 'module2' from '__main__' (C:/_MyFiles/Programming/Python Projects/pgui/mypackage/module1.py)

我不想python -m myfile每次在处理模块并希望将其作为脚本直接运行时都打开控制台并输入。

我希望能够在不将其父文件夹添加到 PYTHONPATH 的情况下通过使用 Python2 中的相对导入来处理模块

这些问题是否有更好的解决方法或解决方案?

标签: pythonpython-3.xpython-importrelative-pathpython-packaging

解决方案


根据模块文档,对于__main__模块,您必须使用绝对导入。

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

所以只需将导入行更改module1.py为:

from mypackage import module2

其他一切都保持不变。


推荐阅读