从子目录导入Python模块时无法找到同目录其他模块的问题
Python跨目录导入模块报错原因解析
这个问题的本质是Python的模块搜索路径规则和相对导入的生效条件共同导致的,Python 3.3+之后已经支持隐式命名空间包,是否添加__init__.py和该报错没有直接关联。
场景1:a.py写from b import functionB的报错原因
- 直接执行
python a.py时,Python会自动将a.py所在的folder2目录的绝对路径添加到模块搜索路径sys.path的首位,此时可以直接检索到同目录下的b.py,导入正常。 - 执行
python external.py时,Python会将external.py所在的根目录添加到sys.path首位,此时sys.path中不存在folder2的路径,a.py作为folder1.folder2.a模块被导入时,执行from b import functionB只会在sys.path下检索名为b的模块,自然检索失败,抛出ModuleNotFoundError。
场景2:a.py写from .b import functionB的报错原因
相对导入的生效前提是:当前文件是作为包的子模块被导入,而非顶层可执行脚本运行。
- 执行
python external.py时,a.py的身份是folder1.folder2.a子模块,Python可以识别到它的父包层级,相对导入.b会自动定位到同目录下的b.py,运行正常。 - 直接执行
python a.py时,Python会将a.py标记为顶层脚本__main__,不承认它属于任何包结构,无法找到父包来解析相对导入路径,因此抛出ImportError: attempted relative import with no known parent package。
通用解决方法
方法1:添加路径兼容逻辑
在a.py开头添加如下代码,区分直接运行和被导入的两种场景:
import sys from pathlib import Path if __name__ == "__main__": # 直接运行时将当前目录加入搜索路径,使用绝对导入 sys.path.append(str(Path(__file__).parent.absolute())) from b import functionB else: # 作为子模块被导入时使用相对导入 from .b import functionB
方法2:统一使用模块方式运行脚本
不要直接在子目录下执行脚本,所有执行操作都在项目根目录完成,要运行a.py时执行以下命令即可:
python -m folder1.folder2.a
此时Python会将项目根目录加入sys.path,同时a.py会被识别为包的子模块,相对导入可以正常生效。
内容的提问来源于stack exchange,提问作者David Schumann
相关产品推荐
相关产品推荐

