You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyInstaller单文件打包使用multiprocessing spawn报FileNotFoundError

问题根因

这个错误是PyInstaller --onefile 打包模式的临时目录机制和multiprocessing spawn启动逻辑的冲突导致的,非稳定复现的特性也和这个机制直接相关:

  • --onefile模式运行时,会先把所有打包的资源、源码解压到系统临时目录下随机命名的_MEIxxx文件夹(即报错中的/tmp/_MEIRtGMqX),主进程退出时会自动递归删除这个临时目录。
  • spawn启动子进程的逻辑是:启动全新的Python解释器进程,通过传入的主模块路径重新加载主模块,再执行目标函数。PyInstaller的运行时钩子本来会把这个路径重定向到打包后的可执行文件本身,一旦钩子未正确生效,子进程就会尝试读取临时目录下的web.py文件。
  • 非稳定复现的核心原因:如果子进程创建时主进程仍在正常运行,临时目录还未被清理,读取web.py就不会报错;如果子进程创建触发时主进程已经进入退出流程、开始清理临时目录,就会出现FileNotFoundError。这种时序问题通常和后台线程触发子进程创建、信号处理逻辑、异步任务延迟调度有关。
  • fork模式不会触发这个问题,是因为fork是直接复制主进程的内存空间生成子进程,不需要重新从磁盘加载主模块文件,自然不会访问临时目录,但也正因为直接复制内存,会把父进程的锁状态一并复制,很容易出现死锁挂起的问题。

注意:Linux原生环境下freeze_support()确实是空逻辑,但PyInstaller打包后会通过pyi_rth_multiprocessing运行时钩子重写这个函数的逻辑,专门用来修正spawn模式下的主模块路径,所以打包后必须正确调用这个方法。你当前的代码存在调用顺序问题:freeze_support()需要在set_start_method('spawn')之前执行,且必须在所有多进程相关逻辑导入、初始化之前运行,否则运行时钩子无法正确拦截spawn的路径传参。

修复方案

按以下步骤调整即可解决问题:

  1. 调整主入口代码顺序,把freeze_support()放到if __name__ == "__main__"块的最开头,先于所有其他逻辑执行:
from multiprocessing import freeze_support, set_start_method

if __name__ == "__main__":
    # 必须第一行调用,不能放在set_start_method后面
    freeze_support()
    set_start_method('spawn')
    # 后续再执行业务逻辑导入、进程创建等操作
  1. 禁止在模块顶层(if __name__ == "__main__"块之外)编写任何会触发进程创建、线程启动的逻辑,也不要在顶层导入会初始化多进程池、后台线程的依赖模块,避免主模块被导入时就触发意外的子进程创建。
  2. 如果调整顺序后仍偶发报错,可以在PyInstaller打包时添加--runtime-tmpdir参数,指定一个不会被自动清理的固定临时目录,避免主进程退出时目录被提前删除,示例命令:
pyinstaller --onefile --runtime-tmpdir /var/run/yourapp web.py

需要保证运行程序的用户对指定的临时目录有读写权限。


内容的提问来源于stack exchange,提问作者TiYan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 23:16:01