相对目录是Python新手最容易踩的坑之一。很多人会有这样的疑问:我有一个Python程序,某些Python文件里面有读写文件的操作,在操作文件的过程中,如果使用的是相对目录,那么这个相对目录是相对于这个Python文件自身吗?
答案是:不是。相对路径是相对于"当前工作目录(CWD)",而不是相对于Python文件自身。
# 无论这行代码写在哪个 .py 文件里
open("config/settings.yaml")
它永远等价于:
open(os.path.join(os.getcwd(), "config/settings.yaml"))
跟这个 .py 文件放在哪个目录完全无关。
CWD 是你启动 Python 解释器时所在的目录,由启动方式决定:
| 启动方式 | CWD |
|---|---|
命令行 cd D:\proj && python examples/chat.py | D:\proj |
命令行 cd D:\proj\examples && python chat.py | D:\proj\examples |
| IDE 直接点 Run(PyCharm/VSCode) | 默认是项目根目录,可配置 |
python -m examples.chat | 你敲命令时所在目录 |
双击 .py 文件 | 该文件所在目录 |
关键点:同一个脚本,换一种启动方式,CWD 就变了,相对路径的解析结果也跟着变。 这就是为什么"我本地能跑,别人一跑就找不到文件"。
在任意 .py 里加:
import os
from pathlib import Path
print("CWD:", os.getcwd())
print("脚本文件位置:", Path(__file__).resolve())
print("相对路径解析成:", Path("config/settings.yaml").resolve())
你会发现 CWD 和脚本位置经常不是同一个。
用 file 手动锚定,这是标准做法:
from pathlib import Path
# 当前 .py 文件所在目录
BASE_DIR = Path(__file__).resolve().parent
# 相对该文件拼路径
filepath = BASE_DIR / "config" / "settings.yaml"
__file__:当前脚本的路径(可能是相对的,取决于启动方式)
.resolve():转成绝对路径,消除 ..、软链接等
.parent:取所在目录
这样不管 CWD 是什么、从哪启动,路径都稳定。
因为 CWD 是进程级的概念,一个进程只有一个 CWD,所有代码(包括标准库、第三方库)共享它。如果相对路径改成"相对文件自身",那标准库、site-packages 里的代码行为都会乱套。所以 Python 选择了"相对 CWD"这个统一规则,把定位文件的责任交给开发者。
相对路径永远相对于进程的当前工作目录 CWD,不是相对于 .py 文件。要让它相对文件自身,必须用 Path(__file__).resolve().parent 手动锚定。
评论专区
评论加载中...登录后即可发表评论