最直接可靠的方式是用 os.path.abspath(__file__) 获取脚本绝对路径,再用 os.path.dirname() 或 pathlib.Path(__file__).resolve().parent 获取所在目录;避免使用 sys.argv[0] 或未标准化的 __file__。

用 os.path.abspath(__file__) 最直接
这是最常用也最可靠的方式,__file__ 是 Python 解释器自动提供的特殊变量,指向当前脚本的路径(可能是相对路径),os.path.abspath() 将其标准化为绝对路径。
注意:它返回的是脚本文件本身的路径,不是当前工作目录(os.getcwd())或执行入口点(比如被 import 时的调用方路径)。
- 在脚本顶层直接使用即可,无需额外判断
- 如果脚本被 symlink 调用,
os.path.abspath()不会自动解析符号链接,返回的是 symlink 的目标路径(即真实路径) - Windows 下返回带盘符的路径,如
C:\project\main.py;Linux/macOS 返回以/开头的路径
想获取脚本所在目录?用 os.path.dirname() 套一层
很多场景真正需要的是脚本所在的文件夹,而不是脚本文件本身。这时候不能只靠 __file__,必须先转成绝对路径再取目录:
import os script_dir = os.path.dirname(os.path.abspath(__file__))
常见错误是写成 os.path.dirname(__file__) —— 如果你在 /home/user 目录下运行 python ./sub/main.py,__file__ 是 ./sub/main.py,os.path.dirname(__file__) 就是 ./sub,这不是绝对路径,后续拼接文件时容易出错。
- 必须先
abspath再dirname,顺序不能反 - 结果末尾不带斜杠,如需拼接子路径,建议用
os.path.join(script_dir, "config.json")而不是字符串拼接
Python 3.4+ 推荐用 pathlib.Path 更简洁
pathlib 是现代 Python 处理路径的首选,语义清晰、跨平台友好:
from pathlib import Path script_path = Path(__file__).resolve() script_dir = script_path.parent
Path(__file__).resolve() 等价于 os.path.abspath(),但额外做了符号链接解析(即返回实际文件位置,不是 symlink 本身)。如果你明确需要保留 symlink 路径,得用 .absolute() 替代 .resolve()。
-
.parent比os.path.dirname()更直观 -
Path对象支持链式操作,比如Path(__file__).resolve().parent / "data" / "input.txt" - 在旧项目中混用
os.path和pathlib没问题,但不要对Path对象直接用os.path.*函数(比如os.path.join(path_obj, ...)),会报错
别踩 sys.argv[0] 这个坑
有人误以为 sys.argv[0] 总是当前脚本路径,但它只是 Python 启动时传入的第一个参数,受调用方式影响极大:
- 运行
python main.py→sys.argv[0]是main.py(相对路径) - 运行
python /full/path/main.py→ 才是绝对路径 - 从 IPython 或 Jupyter 中运行脚本 →
sys.argv[0]可能是ipython或空字符串 - 打包成 exe(如 PyInstaller)后,
sys.argv[0]指向临时解压路径,和源码位置完全无关
所以除非你严格控制执行环境且明确知道 sys.argv[0] 的来源,否则一律避免依赖它获取脚本路径。
真正难处理的是多层 import 场景——比如 a.py 导入 b.py,而你想在 b.py 里拿到 a.py 的路径。这种需求本身就很可疑,通常说明路径逻辑该由调用方显式传入,而不是靠反射硬挖。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











