os.path.abspath(__file__) 最可靠,因__file__指向脚本自身路径,abspath纯字符串标准化为绝对路径,不检查存在性、兼容所有python版本、symlink下行为明确,且不受运行上下文影响。

为什么 os.path.abspath(__file__) 是最可靠的方式
因为 __file__ 是 Python 解释器在加载模块时自动设置的路径字符串,它指向当前脚本文件本身(不是执行时的当前工作目录),而 os.path.abspath() 能把相对路径、符号链接、.. 等全部标准化为真实存在的绝对路径。其他方法比如 os.getcwd() 或拼接 sys.argv[0] 都依赖运行上下文,极易出错。
常见错误现象:os.getcwd() 返回的是终端启动时的目录,不是脚本所在目录;sys.argv[0] 在被 import 时可能变成 "-c" 或空字符串;用 pathlib.Path(__file__).resolve() 虽然等效,但需注意 resolve() 默认会检查路径是否存在(如果文件已被删除会抛 FileNotFoundError)。
-
os.path.abspath(__file__)不检查文件是否存在,纯字符串处理,安全稳定 - 适用于所有 Python 版本(2.7+ 和 3.x)
- 在主脚本和被 import 的模块中行为一致
当脚本被 symlink 调用时要不要用 os.path.realpath
取决于你要“脚本物理位置”还是“脚本被调用的位置”。os.path.abspath(__file__) 返回的是 symlink 本身的绝对路径(即用户看到的路径),而 os.path.realpath(__file__) 会追踪到 symlink 指向的真实文件路径。
使用场景举例:你部署了一个软链接 /opt/myapp/current → /opt/myapp/v2.1.0,然后运行 /opt/myapp/current/run.py。此时:
-
os.path.abspath(__file__)得到/opt/myapp/current/run.py -
os.path.realpath(__file__)得到/opt/myapp/v2.1.0/run.py
多数配置加载、资源查找逻辑应基于真实路径(用 realpath),但日志记录或调试输出有时需要保留 symlink 路径(用 abspath)。
在 PyInstaller 打包后 __file__ 行为的变化
PyInstaller 会把脚本打包进归档,此时 __file__ 指向的是临时解压路径(如 /tmp/_MEIxxxxxx/run.py),不再是源码路径。直接用 os.path.abspath(__file__) 仍能工作,但返回的是运行时路径,不是开发时路径。
正确做法是判断是否为 frozen 环境:
import os import sys <p>if getattr(sys, 'frozen', False):</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill8910" title="361SCAN security check your skill python scripts"><img src="https://img.php.cn/upload/skill/000/000/081/179231049778675.jpg" alt="361SCAN security check your skill python scripts" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill8910" title="361SCAN security check your skill python scripts" class="overflowclass">361SCAN security check your skill python scripts</a> <p class="overflowclass">扫描并分析已安装技能,用于查看指定技能目录的名称、描述和详情,或列出所有已安装的技能。</p> </div> <a rel="nofollow" href="/xiazai/skill8910" title="361SCAN security check your skill python scripts" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div><h1>PyInstaller 打包后</h1><pre class="brush:php;toolbar:false;"><code>script_dir = os.path.dirname(sys.executable)</code>
else:
普通 Python 解释器运行
script_dir = os.path.dirname(os.path.abspath(__file__))
注意:sys.executable 指向打包后的可执行文件,其父目录通常是资源存放位置;不要用 sys._MEIPASS 直接拼路径,它不保证与 __file__ 同级。
跨平台路径拼接别手写斜杠,用 os.path.join 或 pathlib
拿到脚本绝对路径后,下一步往往是定位同级配置文件或子目录,比如 config.yaml 或 data/。硬写 script_path + "/config.yaml" 在 Windows 上会出错(反斜杠问题),也容易漏掉路径分隔符。
推荐方式:
- 继续用
os.path:os.path.join(os.path.dirname(os.path.abspath(__file__)), "config.yaml") - Python 3.4+ 更推荐
pathlib:Path(__file__).parent / "config.yaml"(注意是/运算符,不是除法)
pathlib 写法更简洁,但要注意:如果脚本路径含中文或特殊字符,某些旧版 Windows 系统上 Path 构造可能触发编码问题,此时 os.path 更保守可靠。
真正容易被忽略的是:路径操作结果必须验证存在性再使用。哪怕用了 abspath 和 join,如果目标文件被误删或权限不对,后续 open() 或 os.listdir() 依然会报错——路径“合法”不等于“可用”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










