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

pandas处理速度过慢如何分批执行?Flask渐进式返回前端实现咨询

你这个需求本质是后端分批异步处理 + 前端渐进式加载,用你当前已有的Flask + Pandas + 前端JS技术栈就能实现,不需要额外引入复杂组件,具体步骤如下:


1 先解决当前代码的核心性能问题

你当前函数慢的核心原因是df.apply逐行调用tdp、get_main_task两个数据库查询函数,437条数据就会执行874次独立的SQL查询,这是耗时的根源,先做这个优化就能大幅提升速度:

def get_project_details(pids: list, conn: pymssql._pymssql.Connection) -> dict:
    pidq = ",".join([f"'{x}'" for x in pids])
    query = f"SELECT * FROM VW_CSMS_PMT_ProjectDetails WHERE Project_Id in ({pidq})"
    df = pd.read_sql(
        query,
        con=conn,
        parse_dates=["StartDate", "TargetDate"],
    )
    # 新增:批量查询所有pid对应的关联数据,仅执行2次SQL
    all_timesheet = get_batch_tdp(pids, conn) # 自行实现该函数,一次性查询所有pid的timesheet数据,返回{project_id: 详情}的字典
    all_main_task = get_batch_main_task(pids, conn) # 同上,一次性查询所有pid的主任务数据
    
    out = df.apply(
        lambda x: {
            "id": x["Project_Id"],
            "type": "project",
            "name": x["Project_Name"],
            "start_date": get_date_string(x["StartDate"]),
            "target_date": get_date_string(x["TargetDate"]),
            "estimate": x["EST_HRS"],
            "status": x["status"],
            # 直接从预查的字典取数据,不用每次查库
            "timesheet_details": all_timesheet.get(x["Project_Id"]),
            "main_task": all_main_task.get(x["Project_Id"]),
        },
        axis=1,
    )

    if isinstance(out, pd.core.series.Series):
        out = out.tolist()
    else:
        out = None
    return out

2 实现分批处理+前端渐进渲染逻辑

如果优化后还是需要实现先展示前10条、后台逐步返回剩余数据的需求,用Flask原生支持的SSE(服务器推送事件)实现即可,不需要前端轮询,效率更高:

2.1 后端Flask接口实现

首先写一个分组工具函数,再写SSE推送接口:

from flask import Response, request
import json

# 按固定大小切分列表
def split_batch(lst, batch_size=10):
    return [lst[i:i+batch_size] for i in range(0, len(lst), batch_size)]

@app.route('/process_projects', methods=['POST'])
def process_projects():
    all_pids = request.json.get('pids', [])
    batches = split_batch(all_pids)
    conn = 你的数据库连接
    
    def generate_stream():
        # 先返回第一批次数据,前端立即渲染
        first_batch = get_project_details(batches[0], conn)
        yield f'data: {json.dumps({"batch_index": 0, "total_batches": len(batches), "data": first_batch})}\n\n'
        # 后台逐批处理剩余数据,每处理完一批推送一次
        for idx in range(1, len(batches)):
            batch_data = get_project_details(batches[idx], conn)
            yield f'data: {json.dumps({"batch_index": idx, "total_batches": len(batches), "data": batch_data})}\n\n'
    
    return Response(generate_stream(), mimetype='text/event-stream')

2.2 前端接收渲染逻辑

用原生JS监听SSE推送的消息,每收到一批数据就追加到页面列表中:

// 你的全量项目ID列表
const allPids = [你的437个pid数组];
const projectListDom = document.getElementById('project-list'); // 页面上的列表容器

// 建立SSE连接
const evtSource = new EventSource('/process_projects', {
    method: 'POST',
    body: JSON.stringify({pids: allPids}),
    headers: {'Content-Type': 'application/json'}
});

// 监听推送消息
evtSource.onmessage = function(event) {
    const res = JSON.parse(event.data);
    // 渲染当前批次的10条数据,追加到列表末尾
    res.data.forEach(project => {
        const item = document.createElement('div');
        item.innerText = project.name; // 按你的需求渲染字段
        projectListDom.appendChild(item);
    });
    // 所有批次处理完成,关闭连接
    if (res.batch_index === res.total_batches - 1) {
        evtSource.close();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 07:45:01