如何让多个Flask客户端共享同一个生成器实例?
实现Flask SSE新客户端从当前进度续传
问题场景
当前代码中,每个新客户端访问localhost:5000时,都会从头开始生成小写字母序列。需要修改为新接入的客户端直接从已有客户端的当前进度继续输出,而非重复从头开始。
核心思路
问题根源在于每个请求的generate()生成器都是独立实例,没有共享进度状态。解决方法是:维护一个全局共享的进度变量,所有生成器都基于这个变量的当前值开始输出,同时保证多线程环境下的线程安全(Flask开发服务器默认多线程)。
修改后的代码实现
修改app/views/views.py文件,添加全局进度控制逻辑:
import time, string import threading from flask import Blueprint, Response public = Blueprint('views', __name__) # 全局进度变量:记录当前已输出到第几个字母(初始为0) current_index = 0 # 线程锁:保证多线程环境下修改进度的安全性 index_lock = threading.Lock() def generate(): letters = list(string.ascii_lowercase) global current_index # 加锁获取当前进度,避免多线程冲突 with index_lock: start_idx = current_index # 如果已经输出完所有字母,直接返回结束信号 if start_idx >= len(letters): yield "event: end\r\ndata: 所有内容已输出完毕\r\n\r\n" return # 从当前进度开始遍历输出 for i in range(start_idx, len(letters)): l = letters[i] yield f"var: {l} \r\n" time.sleep(1) # 加锁更新全局进度:只有当前生成器是最新进度时才更新,避免重复推进 with index_lock: if current_index == i: current_index += 1 # 所有字母输出完成后发送结束信号 yield "event: end\r\ndata: 所有内容已输出完毕\r\n\r\n" @public.route('/') def feed(): return Response( generate(), content_type='text/event-stream', mimetype='multipart/x-mixed-replace' )
关键说明
- 全局进度变量:
current_index记录当前已经输出到的字母位置,所有新连接的生成器都从这个位置开始。 - 线程安全:使用
threading.Lock()对进度变量的读写操作加锁,避免多线程环境下的竞态条件(比如多个生成器同时修改进度导致的混乱)。 - 结束处理:当所有字母输出完成后,新客户端连接会直接收到结束信号,无需等待。
适配实际项目
如果实际项目中是调用第三方生成类,只需将上述逻辑迁移:
- 为生成类维护全局的进度状态(比如当前生成的位置、已完成的步骤等)。
- 每个新的生成实例从全局进度状态开始执行。
- 若生产环境使用多进程服务器,需改用Redis等外部存储来共享进度(全局变量无法跨进程共享)。
内容的提问来源于stack exchange,提问作者destinychoice
相关产品推荐
相关产品推荐

