Flask使用multiprocessing时点击停止按钮无法获取进程内追加的列表如何解决
问题原因
- Python多进程默认内存隔离,每个子进程启动时会复制主进程的全部资源副本,子进程
test函数中修改的logs是子进程专属的内存副本,和主进程的logs没有关联,所以主进程打印时得到的还是初始的空列表。 - 你提供的原始代码还缺少
time、request、redirect、url_for、render_template的导入,运行时会触发导入错误。
解决方案
使用multiprocessing.Manager提供的跨进程共享列表存储数据,修改后可正常运行的代码如下:
from multiprocessing import Process, Manager from flask import Flask, request, redirect, url_for, render_template import time app = Flask(__name__) # 初始化跨进程共享管理器 manager = Manager() # 创建跨进程共享的列表,所有进程对该列表的修改会自动同步 logs = manager.list() # 提前初始化全局进程变量,避免首次点击停止按钮时报变量未定义错误 p = None def test(): for i in range(100): logs.append(i) time.sleep(1) @app.route('/', methods=['POST', 'GET']) def main(): global p if request.method == 'POST': index = request.form['index'] if index == 'start': # 增加进程状态判断,避免重复启动进程报错 if p is None or not p.is_alive(): p = Process(target = test) p.start() if index == 'stop': if p is not None and p.is_alive(): p.kill() # 共享列表转普通列表后打印,后续操作更方便 print(list(logs)) # 如果需要下次启动进程时清空历史数据,可取消下一行注释 # logs[:] = [] return redirect(url_for('main')) return render_template('index.html') if __name__ == '__main__': # debug模式默认会启动重载进程,会导致共享管理器重复初始化,必须加use_reloader=False app.run(debug=True, use_reloader=False)
注意事项
- 不要对共享列表做整体赋值操作,比如
logs = [1,2,3]会把共享列表替换成普通列表,失去跨进程同步能力,需要修改时用append、extend或者切片赋值logs[:] = [1,2,3]这类方法。 - 如果要往共享列表里存储复杂对象,要确保对象可序列化,否则会触发运行错误。
内容的提问来源于stack exchange,提问作者Dmitry
相关产品推荐
相关产品推荐

