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

PyInstaller打包使用tqdm的Python程序退出时异常重启问题

问题现象

开发的Python程序支持可选调用tqdm为长耗时计算场景展示进度条,使用PyInstaller完成打包后存在如下表现:

  • 未启用tqdm功能时,打包后的程序可正常运行至流程结束,无异常
  • 启用tqdm时,程序可正常展示进度条、运行至流程末尾,随后抛出警告信息,且打包后的程序会携带错误参数自动重启

抛出的警告内容如下:

multiprocessing/resource_tracker.py:104: UserWarning: resource_tracker: process died unexpectedly, relaunching. Some resources might leak.

程序调用tqdm的逻辑为遍历列表成员的普通循环,本身未主动导入multiprocessing模块,核心实现代码:

def best_cost(self, guesses, steps=1, verbose=0) -> None:
    """ find the guess with the minimum cost """
    self.cost = float("inf")
    for guess in guesses if verbose < 3 else tqdm(guesses, mininterval=1.0):
        groups = dict()
        for (word, frequency) in self.words.items():
            result = calc_result(guess, word)
            groups.setdefault(result, {})[word] = frequency
        self.check_cost(guess, groups, steps=steps)
    return
复现环境
  • 硬件系统:搭载Intel处理器的macOS Monterey V12.4
  • Python版本:3.10.4(Python 3.9版本下问题同样存在)
  • 运行环境:virtualenv虚拟环境,pip安装依赖版本为pyinstaller 5.1、pyinstaller-hooks-contrib 2022.7、tqdm 4.64.0
  • 复现规律:PyInstaller无论使用--onedir还是--onefile参数打包,问题均稳定复现;问题仅出现在打包后的程序中,IDE内直接运行源码无异常,无法通过VSCode等工具直接调试排查。
根因分析

根据multiprocessing模块官方文档说明:Unix系统下使用spawn或forkserver启动方式时,会额外启动resource_tracker进程,负责跟踪程序进程创建的未链接命名系统资源(如命名信号量semaphores、SharedMemory对象);所有进程退出后resource_tracker会清理剩余被追踪对象,正常场景下无剩余资源,若进程被信号杀死则可能出现资源泄漏——泄漏的信号量、共享内存段在系统重启前不会自动清理,既可能触发系统命名信号量数量限制,也会占用物理内存空间。
该问题触发逻辑如下:

  • 业务代码本身未主动导入、使用multiprocessing模块
  • tqdm内部会自动导入multiprocessing模块,为进度条实例创建基于信号量的锁,且未提供手动删除信号量资源的公开方法,按设计该类资源应在程序结束时自动释放
  • PyInstaller打包后的程序运行时本身也会调用multiprocessing模块,打包后的运行环境会干扰tqdm所持信号量资源的正常释放顺序,导致resource_tracker误判主进程异常退出,抛出警告并触发程序自动重启。
可行解决方案
  • 强制tqdm禁用multiprocessing锁:初始化tqdm时传入lock_args=False参数,直接关闭tqdm内部基于multiprocessing创建的信号量锁,单进程场景下不会对进度条展示、功能逻辑产生任何影响,可从根源避免resource_tracker追踪tqdm创建的信号量资源,修改示例如下:
for guess in guesses if verbose < 3 else tqdm(guesses, mininterval=1.0, lock_args=False):
  • 入口处添加multiprocessing打包兼容配置:在代码最外层if __name__ == '__main__':块的首行添加PyInstaller冻结支持配置,同时强制multiprocessing使用fork启动模式(macOS下Python 3.8+默认启动模式为spawn,是触发resource_tracker独立进程启动的直接原因),配置代码如下:
import multiprocessing

if __name__ == '__main__':
    multiprocessing.freeze_support()
    multiprocessing.set_start_method('fork', force=True)
    # 原有业务主逻辑从这里开始

注意:使用该方案前需确认程序所有依赖库兼容fork启动模式,若存在线程、锁相关的兼容异常,优先选择第一种方案。

  • 升级依赖到修复版本:将pyinstaller升级至5.3及以上版本、tqdm升级至4.66.0及以上版本,高版本依赖已经修复了部分打包场景下multiprocessing资源清理顺序错乱的问题,升级后无需修改业务代码即可解决部分场景下的异常重启问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 01:45:36