Flask流式数据无法实时更新:仅停服务后才显示数据求助
问题分析与解决方案
这问题我太熟了,核心原因是Flask默认的单线程运行模式在搞鬼,再加上你的代码里对/api/stream的GET和POST请求没做区分,直接导致了请求阻塞。
为什么会出现这种情况?
- Flask默认是单线程、单进程运行的,同一时间只能处理一个请求。当你发送POST请求到
/api/stream时,这个请求会进入event_stream的无限循环,一直占用着唯一的线程。 - 当你打开
/api/output时,浏览器会发起GET请求到/api/stream建立SSE连接,但这个请求被前面的POST请求死死堵住,根本得不到响应。 - 只有当你停止Flask服务,那个卡住的POST请求被终止,所有缓存的SSE数据才会一次性发送给浏览器,所以你看到停服务后才弹出所有数字。
怎么解决?
我给你三个递进的解决方案,按需选择:
1. 开启Flask的多线程模式
最简单的临时解决办法,启动Flask时加上threaded=True参数,让它能同时处理多个请求:
if __name__ == '__main__': application.run(threaded=True)
这样POST请求和SSE的GET请求就不会互相阻塞了,浏览器能实时收到SSE数据。
2. 区分GET和POST请求的处理逻辑
你的POST请求明显不是来获取SSE流的,应该把/api/stream的GET和POST分开处理,避免POST请求进入无限循环:
# 专门处理SSE的GET请求 @application.route('/api/stream', methods=['GET']) def stream(): def event_stream(): n = 0 while True: yield "data: %s\n\n" % n n += 1 time.sleep(1) return Response(event_stream(), mimetype='text/event-stream') # 专门处理POST请求 @application.route('/api/stream', methods=['POST']) def handle_stream_post(): # 这里写你实际要处理的POST逻辑,比如接收参数、触发任务等 return "POST request processed"
这样POST请求处理完就会返回,不会占用线程,SSE连接也能正常建立并实时推送数据。
3. 用异步任务处理耗时操作(进阶)
如果你的POST请求是要触发一个耗时任务,然后通过SSE推送任务进度,那单线程/多线程可能不够用,建议用后台线程或者异步任务队列(比如Celery)来处理任务,避免阻塞请求线程。举个简单的后台线程例子:
from threading import Thread from flask import request # 存储客户端的SSE连接(简单实现,实际可用Redis等存储) clients = [] @application.route('/api/stream', methods=['GET']) def stream(): def event_stream(): # 将当前连接加入客户端列表 clients.append(event_stream) try: n = 0 while True: yield "data: %s\n\n" % n n += 1 time.sleep(1) finally: # 连接关闭时移除客户端 clients.remove(event_stream) return Response(event_stream(), mimetype='text/event-stream') @application.route('/api/stream', methods=['POST']) def trigger_task(): def background_task(): # 模拟耗时任务并推送进度 for i in range(10): time.sleep(1) # 给所有客户端推送进度 for client in clients: client(f"data: Task progress: {i*10}%\n\n") # 任务完成推送结束信号 for client in clients: client("data: Task completed\n\n") # 启动后台线程执行任务 Thread(target=background_task).start() return "Task started"
这种方式更适合实际的进度推送场景,不会阻塞主线程,也能正确处理多个客户端的SSE连接。
内容的提问来源于stack exchange,提问作者Daniel Koczuła
相关产品推荐
相关产品推荐

