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

含并行处理的Python代码打包exe后陷入无限自调用循环问题

解决PyInstaller打包joblib并行代码的无限递归问题

问题原因

使用pyinstaller --onefile打包含joblib Parallel的代码时,单文件exe运行会临时解压到系统临时目录。joblib启动子进程时,会误将当前exe文件当作Python解释器调用,导致程序反复启动自身,陷入无限循环。

解决方案

方法1:修改代码指定Python解释器路径

在初始化Parallel时,通过loky后端的参数指定正确的Python解释器路径,同时判断是否处于打包后的环境:

# example.py
from math import sqrt
from joblib import Parallel, delayed
import sys
import os

def producer():
    for i in range(6):
        print('Produced %s' % i)
        yield i

def main():
    is_frozen = getattr(sys, 'frozen', False)
    python_executable = sys.executable
    
    if is_frozen and hasattr(sys, '_MEIPASS'):
        # 打包后从临时解压目录获取Python解释器
        python_executable = os.path.join(sys._MEIPASS, 'python.exe')

    out = Parallel(
        n_jobs=2, 
        verbose=100, 
        pre_dispatch='1.5*n_jobs',
        backend='loky',
        loky_kwargs={'executable': python_executable}
    )(delayed(sqrt)(i) for i in producer())

if __name__ == '__main__':
    main()

打包命令:

pyinstaller --onefile --collect-submodules joblib example.py

方法2:切换到multiprocessing后端并配置启动方式

改用multiprocessing作为joblib的后端,并在冻结环境下设置进程启动方式:

# example.py
from math import sqrt
from joblib import Parallel, delayed
import sys
import multiprocessing

def producer():
    for i in range(6):
        print('Produced %s' % i)
        yield i

def main():
    if getattr(sys, 'frozen', False):
        multiprocessing.set_start_method('spawn')
    
    out = Parallel(
        n_jobs=2, 
        verbose=100, 
        pre_dispatch='1.5*n_jobs',
        backend='multiprocessing'
    )(delayed(sqrt)(i) for i in producer())

if __name__ == '__main__':
    main()

打包命令:

pyinstaller --onefile example.py

验证

运行打包后的exe文件,若正常打印Produced x系列日志并完成计算,说明问题已解决,程序不再陷入无限循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 13:46:01