如何检测当前代码是否运行在 PyInstaller 打包后的 exe 中

是,通过检查 sys.frozen 属性可准确判断是否运行在 PyInstaller 打包后的可执行文件中:若为 True 则是打包后运行,此时应使用 sys._MEIPASS 获取资源路径;否则为正常解释器运行。

可以通过检查 sys.frozen 属性来判断代码是否运行在 PyInstaller 打包后的可执行文件中。

检查 sys.frozen 是否为 True

PyInstaller 在打包后会将 sys.frozen 设为 True,这是最直接、最可靠的判断方式:

  • 未打包时:sys.frozen 不存在或为 False
  • 打包后(exe 运行时):sys.frozen == True

推荐写法:

import sys
if getattr(sys, 'frozen', False):
  # 正在以 PyInstaller 打包后的 exe 方式运行
  bundle_dir = sys._MEIPASS
else:
  # 正常 Python 解释器运行
  bundle_dir = os.path.dirname(os.path.abspath(__file__))

配合 sys._MEIPASS 获取资源路径

打包后,PyInstaller 会把数据文件解压到临时目录,并通过 sys._MEIPASS 暴露该路径。这个属性仅在 sys.frozen == True 时有效:

  • 不要直接使用 os.getcwd()__file__ 查找资源(它们指向临时目录或无效路径)
  • 统一用 sys._MEIPASS 构建资源路径,例如:os.path.join(sys._MEIPASS, 'data', 'config.json')
  • 建议封装一个函数自动适配开发和发布环境

避免依赖其他易变的判断方式

以下方法不推荐作为主要判断依据:

  • sys.executable 结尾是否为 .exe:Windows 下可能误判(如 python.exe 也带 .exe),跨平台不可靠
  • 检查进程名或命令行参数:容易被绕过,且增加复杂度
  • 依赖特定目录结构或文件存在:打包配置变更后易失效

sys.frozen 是 PyInstaller 官方文档明确支持的标识,稳定、轻量、语义清晰。