You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让多个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()对进度变量的读写操作加锁,避免多线程环境下的竞态条件(比如多个生成器同时修改进度导致的混乱)。
  • 结束处理:当所有字母输出完成后,新客户端连接会直接收到结束信号,无需等待。

适配实际项目

如果实际项目中是调用第三方生成类,只需将上述逻辑迁移:

  1. 为生成类维护全局的进度状态(比如当前生成的位置、已完成的步骤等)。
  2. 每个新的生成实例从全局进度状态开始执行。
  3. 若生产环境使用多进程服务器,需改用Redis等外部存储来共享进度(全局变量无法跨进程共享)。

内容的提问来源于stack exchange,提问作者destinychoice

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 12:37:31