os.path.abspath(__file__)最可靠,因其不依赖当前工作目录且自动解析符号链接;而sys.argv[0]在import、-m运行或os.chdir()后易失效;推荐Python 3.4+用pathlib.Path(__file__).resolve()。

为什么 os.path.abspath(__file__) 是最常用解法
因为 __file__ 在绝大多数情况下(普通脚本、模块导入)都指向当前 Python 文件的路径,而 os.path.abspath() 能把相对路径转成绝对路径,还能自动处理 .. 和 .。它不依赖工作目录,也不需要额外判断是否被压缩包或冻结可执行文件调用——只要不是极端打包场景,这条组合就稳。
常见错误现象:os.getcwd() 返回的是终端当前目录,不是脚本所在目录;直接读 __file__ 可能是相对路径(比如你从上级目录运行 python sub/main.py,__file__ 就是 "sub/main.py")。
- 始终用
os.path.abspath(__file__),别省略os.path.前缀(abspath不在os根命名空间里) - 如果脚本可能被
exec()或字符串动态加载,__file__可能不存在或为None,需加if hasattr(sys, '_getframe') and '__file__' in globals():防御 - Windows 下返回路径含反斜杠,但 Python 字符串和
os.path函数能正常处理,无需手动替换
当脚本被 PyInstaller 打包后 __file__ 失效怎么办
PyInstaller 把代码解压到临时目录运行,此时 __file__ 指向临时路径,不是原始开发路径。你需要区分“资源位置”和“脚本位置”——多数人真正想要的是资源(如配置文件、图片)所在的目录,而非打包前的源码路径。
正确做法是用 sys._MEIPASS(PyInstaller 专用)配合 getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__))) 回退:
import sys import os <p>if getattr(sys, 'frozen', False):</p><h1>打包后</h1><pre class="brush:php;toolbar:false;">application_path = sys._MEIPASS
else:
开发时
application_path = os.path.dirname(os.path.abspath(__file__))
config_path = os.path.join(application_path, 'config.json')
注意:sys.frozen 是 PyInstaller 注入的标志,其他打包工具(如 cx_Freeze)用不同机制,不能直接复用这段逻辑。
pathlib.Path(__file__).resolve() 比 os.path.abspath() 好在哪
pathlib 是 Python 3.4+ 官方推荐的路径操作方式,.resolve() 不仅等价于 abspath(),还会真实解析符号链接(abspath() 不解析),且返回 Path 对象,后续拼接、读写更自然。
- 推荐写法:
from pathlib import Path; script_dir = Path(__file__).parent.resolve()(.parent直接得目录,不用再dirname) -
.resolve()在路径不存在时会抛FileNotFoundError,而abspath()照常返回“看起来合理”的路径——这既是优点也是坑,调试时容易暴露路径误配 - 跨平台兼容性一致,但旧项目若需支持 Python os.path
获取脚本所在目录时,__file__ 和 inspect.getfile(inspect.currentframe()) 有啥区别
几乎没区别——两者在常规脚本中都返回相同路径。但 inspect.getfile() 更重、更慢,且在某些优化模式(如 python -O)下可能失效;而 __file__ 是编译期注入的,稳定可靠。
唯一值得注意的场景:你在交互式解释器(IPython / Jupyter)里粘贴这段代码,__file__ 根本不存在,会触发 NameError;此时 inspect.currentframe() 也能拿到帧对象,但 getfile() 返回 "<stdin>"</stdin> 或 "<ipython-input-1-...>"</ipython-input-1-...>,无法用于定位磁盘路径。
所以除非你在写调试工具或动态分析库,否则别绕远路——__file__ 就是设计来干这事的。
真正容易被忽略的是:路径操作本身不触发磁盘 I/O,但后续用它打开文件时,权限、符号链接循环、挂载点变更这些底层问题才会暴露。别只盯着“怎么拿到路径”,要同步检查路径是否可读、是否存在、是否是你预期的层级结构。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











