调用Python包脚本遇ModuleNotFoundError,直接运行模块文件正常
解决方案
要同时兼容直接运行脚本和安装后执行命令两种场景,需要调整模块导入逻辑,并修正依赖文件的导入方式:
1. 修正module2.py的导入
module2.py作为包内模块,必须使用相对导入:
""" module2 module. """ from .module1 import Module1 class Module2(Module1): def func1(self): print("module2.func1")
2. 调整__main__.py的导入逻辑
在__main__.py中加入异常捕获,适配两种运行场景:
""" __main__ module """ try: # 安装后作为包运行时,使用绝对导入 from package1.module1 import Module1 from package1.module2 import Module2 except ImportError: # 直接运行__main__.py时,使用相对导入 from .module1 import Module1 from .module2 import Module2 def main(): print("main!") module1 = Module1() module1.func1() module2 = Module2() module2.func1() # 对应pyproject.toml中的脚本配置,暴露__main__函数 __main__ = main if __name__ == "__main__": main()
3. 可选优化:使用python -m package1运行
如果可以接受修改直接运行的命令,也可以不用修改__main__.py,直接用python -m package1代替python package1/__main__.py。这种方式会把package1当作包来加载,此时相对导入可以正常工作,同时安装后的package1命令也不受影响。
原理说明
- 直接运行
python package1/__main__.py时,Python会把package1目录当作脚本所在目录加入sys.path,此时脚本不属于包的一部分,相对导入会失效;而绝对导入找不到package1包(因为项目根目录不在sys.path里)。 - 安装后运行
package1时,package1是作为标准包存在于sys.path中,此时绝对导入有效,但原脚本中的相对导入(或无前缀导入)会找不到模块。 - 用
try-except的方式可以同时适配两种场景,优先尝试绝对导入(安装后场景),失败则切换到相对导入(直接运行脚本场景)。
内容的提问来源于stack exchange,提问作者massi
相关产品推荐
相关产品推荐

