Dash应用中链式启动multiprocessing子进程卡住无法执行问题咨询
问题底层运行机制
该问题和系统资源限制无关,核心是两个Windows平台+Python多进程+Dash调试模式的特性共同导致的:
- Windows系统下Python的
multiprocessing模块默认使用spawn启动方式创建新进程,和Unix系统的fork不同,spawn会启动全新的Python解释器实例,重新导入当前主模块后再执行目标函数。如果嵌套创建子进程时没有做全局配置,子进程的导入初始化阶段会出现上下文异常,导致进程启动失败卡住。 - 示例代码开启了Dash的
debug=True模式,该模式默认会启动Werkzeug重载器,会额外生成一个重载监控进程,打乱了多进程的上下文环境,嵌套创建子进程时会直接导致二级子进程(也就是run_function对应的进程)初始化失败。
解决方案
按如下步骤修改即可解决子进程无法启动的问题:
- 主入口处显式添加
multiprocessing.freeze_support(),这是Windows下运行多进程(尤其是嵌套多进程)的必须配置。 - 要么关闭Debug模式,要么显式禁用重载器:添加
use_reloader=False参数,避免额外的监控进程干扰多进程上下文。 - 可显式指定多进程启动方式为spawn,避免环境默认配置差异。
修正后可正常运行的代码如下:
import multiprocessing import time import dash from dash import html from dash.dependencies import Input, Output app = dash.Dash(__name__) app.layout = html.Div([ html.Button(id='refresh-button', children='Button'), html.Div(id='dynamic-container1') ]) def run_function(i): print('hello') time.sleep(15) print(f'hello world {i}') def run_process(): num = 1 print('hello world 00000') process = multiprocessing.Process(target=run_function, args=(num,)) process.start() process.join() print('hello world') @app.callback(Output('dynamic-container1', 'children'), Input('refresh-button', 'n_clicks')) def refresh_state(click): if click == 0 or click is None: return None p = multiprocessing.Process(target=run_process) p.start() p.join() return None if __name__ == '__main__': # Windows多进程必须配置 multiprocessing.freeze_support() # 显式指定启动方式 multiprocessing.set_start_method('spawn') # 禁用重载器避免多进程冲突,不需要debug可以直接设置debug=False app.run_server(debug=True, use_reloader=False)
额外提示:当前代码中回调函数里直接调用
p.join()会阻塞Dash的回调线程,导致按钮点击后页面长时间处于加载状态,如果不需要等待进程执行结果返回前端,可以去掉join调用,让进程后台独立运行即可。
内容的提问来源于stack exchange,提问作者cool
相关产品推荐
相关产品推荐

