Flask使用subprocess调用外部py脚本 停止时如何获取回调数据
Flask子进程回调获取数组解决方案
核心问题:你当前直接调用process.kill()会强制发送SIGKILL信号终止子进程,子进程内存中的数据未做持久化/输出就被系统回收,无法直接获取,需要通过信号捕获+进程间通信机制实现需求,以下是改动最小的实现方案:
实现步骤
- 改造被调用的
test.py:注册终止信号监听器,收到终止信号时将数组序列化后输出到标准输出再主动退出 - 改造Flask主程序:启动子进程时绑定标准输出管道,停止时发送可被捕获的SIGTERM信号,等待子进程退出后读取标准输出内容反序列化为数组
完整代码示例
1. test.py 代码
import signal import json import sys import time # 替换为你实际生成的数组 my_array = [] # 模拟业务逻辑:持续生成数组元素 def run_business(): global my_array count = 0 while True: my_array.append(count) count += 1 time.sleep(1) # 信号处理函数:收到终止信号时输出数组 def on_terminate(signum, frame): # 序列化数组输出到标准输出 print(json.dumps(my_array)) # 强制刷新缓冲区避免数据残留 sys.stdout.flush() sys.exit(0) # 注册SIGTERM信号监听 signal.signal(signal.SIGTERM, on_terminate) if __name__ == "__main__": run_business()
2. Flask主程序代码
from flask import Flask, render_template, request, redirect, url_for import subprocess import json app = Flask(__name__) # 测试用全局变量存储子进程,生产环境请改用Redis/数据库存储 process = None @app.route('/', methods=['POST', 'GET']) def main(): global process result_array = None if request.method == 'POST': index = request.form['index'] if index == 'start': # 启动子进程时绑定标准输出管道 process = subprocess.Popen( ['python', 'test.py'], stdout=subprocess.PIPE, text=True ) if index == 'stop' and process is not None: # 发送SIGTERM信号触发子进程的善后逻辑,不要用kill process.terminate() # 等待子进程正常退出 process.wait() # 读取子进程输出的数组数据 output = process.stdout.read() if output: result_array = json.loads(output) # 此处可做存储、返回前端等后续操作 print(f"获取到的子进程数组:{result_array}") process = None return redirect(url_for('main')) # 数组可直接传入模板渲染给前端 return render_template('index.html', array=result_array) if __name__ == "__main__": app.run(debug=True)
注意事项
- Windows系统不支持SIGTERM信号,可改用SIGBREAK,或换用临时文件方案:子进程定时将数组写入临时文件,停止后主进程直接读取临时文件即可
- 生产环境多worker部署时不要用全局变量存储process对象,可改用Redis缓存存储进程PID和通信标识
- 数组体积较大时可改用pickle做二进制序列化,传输效率更高
内容的提问来源于stack exchange,提问作者Dmitry
相关产品推荐
相关产品推荐

