最可靠的方式是检查 getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):打包时 sys.frozen 为 True 且 _MEIPASS 存在,开发时两者均不满足,可准确区分环境并获取正确路径。
可以通过检查 sys.frozen 属性是否存在且为 True 来判断当前是否运行在 PyInstaller 打包的可执行文件中。
PyInstaller 在打包后会将 sys.frozen 设置为 True,这是最直接、最可靠的检测方式:
sys.frozen 属性不存在(访问会抛出 AttributeError)sys.frozen == True
import sys is_pyinstaller = getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS')
其中 _MEIPASS 是 PyInstaller 运行时解压资源的临时路径,与 frozen 一起使用可进一步确认环境,避免误判(例如某些其他打包工具也可能设置 frozen)。
打包后,__file__ 指向的是临时解压路径中的 .pyc 文件,不再反映原始位置。应使用

sys._MEIPASS:PyInstaller 解压资源的绝对路径(仅在 frozen 状态下存在)import sys import osdef get_root_path(): if getattr(sys, 'frozen', False):
打包后:可执行文件所在目录
return sys._MEIPASS else: # 开发时:.py 文件所在目录 return os.path.dirname(os.path.abspath(__file__))root = get_root_path()
该检测常用于以下场景:
_MEIPASS)watchdog、auto-py-to-exe)不要依赖以下方式判断:
sys.executable 名称(Windows 上可能为 python.exe 或 exe,但名称不固定,且可被重命名)__file__ 是否含 .exe(打包后它通常指向 .pyc,不是 exe)hasattr(sys, '_MEIPASS')(某些旧版或非标准打包行为可能缺失)稳妥做法始终是组合判断:getattr(sys, 'frozen', False) + hasattr(sys, '_MEIPASS')。