You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python隐式相对导入机制及包目录定义的技术疑问

Python隐式相对导入的工作逻辑与你的场景解析

这个问题其实戳中了Python模块导入机制里一个很容易混淆的点——直接运行脚本和作为包模块运行的区别,咱们一步步拆解来看:

第一个场景的运行逻辑

先看你最初的文件结构:

pkg/
pkg/__init__.py
pkg/main.py # import string
pkg/string.py # print("Package's string module imported")

当你运行python pkg/main.py时,Python会把pkg/目录加入到sys.path的最前端(因为这是你运行的脚本所在的目录)。此时执行import string,Python会按照sys.path的顺序查找模块:

  • 先在pkg/目录下找string.py,刚好存在,所以直接加载这个本地模块,也就输出了你看到的内容。

第二个场景的核心误解

再看修改后的结构:

pkg/
pkg/__init__.py
pkg/core/__init__.py
pkg/core/main.py # import string
pkg/string.py # print("Package's string module imported")

当你运行python pkg/core/main.py时,Python会把pkg/core/目录作为sys.path的第一个元素,而不是你以为的pkg/目录。这是因为你直接运行的是core/main.py这个脚本文件,Python会将该脚本所在的目录视为“顶级目录”,而非把pkg当作一个完整的包来处理。

此时执行import string,Python的查找顺序是:

  1. 先在pkg/core/目录下找string.py——不存在;
  2. 接着遍历sys.path的其他路径(包括Python内置模块的路径),最终找到内置的string模块并加载。

你之前的理解有误:隐式相对导入的“包目录查找”规则,只在模块被当作包的一部分加载时生效,而不是直接运行脚本文件的时候。直接运行脚本时,它是作为“独立的顶级脚本”存在的,而非pkg包的一部分,自然不会去父目录pkg/下查找模块。

如何让第二个场景加载本地的string.py

如果想让core/main.py加载pkg/string.py,你有几种可行的方式:

1. 用模块方式运行脚本

在pkg的父目录下,执行:

python -m pkg.core.main

此时Python会把pkg的父目录加入sys.path,并将pkg视为一个包,core/main.py作为包内的模块,此时import string会先在pkg目录下查找,就能加载到你的本地模块。

2. 使用显式相对导入

修改pkg/core/main.py的代码为:

from .. import string

不过这种方式同样要求你用python -m pkg.core.main来运行,直接运行脚本会报错(因为相对导入不能在顶级脚本中使用)。

3. 手动修改sys.path

在core/main.py的开头添加代码,把pkg目录加入sys.path:

import sys
from pathlib import Path
sys.path.append(str(Path(__file__).parent.parent))

import string

这样不管你怎么运行core/main.py,都会先去pkg目录下查找模块。

内容的提问来源于stack exchange,提问作者Nishant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:25:46