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

Python高效读取多工作表大Excel并转指定JSON方案问询

我之前处理过类似的大Excel文件转JSON的需求,pandas确实在这种场景下有点力不从心,结合你提到的痛点,整理了一套高效的解决方案,不仅能提速,还能满足多线程处理和进度打印的要求:

高效处理多工作表大Excel并生成目标JSON的方案

核心思路

pandas的read_excel慢主要是因为它会做很多额外的封装(比如数据类型推断、索引构建),对于100MB级的文件开销很大。我们换用更轻量的原生Excel读写库直接操作工作表,同时利用多线程并行处理IO密集的读取任务和CPU密集的聚合任务,再配合进度提示功能。

步骤1:准备依赖库

针对.xlsx文件,推荐用openpyxl(原生支持只读模式读取,速度比pandas快很多);如果是.xls格式,用xlrd(注意xlrd 2.0+不再支持xlsx,需安装xlrd<2.0)。另外用tqdm做进度条,concurrent.futures实现多线程:

pip install openpyxl tqdm

步骤2:多线程并行读取工作表

读取不同工作表是典型的IO操作,适合用多线程并行执行,能把串行的等待时间压缩成并行,大幅减少总读取耗时。

步骤3:数据预处理与聚合

  • 先把工作表A的内容转成id -> (name, address)的字典,方便后续快速查询基础信息
  • 把work_1和work_2的所有call记录按id分组收集
  • 最后将每个id的基础信息和对应的call日志合并成你需要的JSON格式

步骤4:批量处理+进度打印

用tqdm实时显示读取和处理进度,同时把id列表分成小批次,用线程池批量处理聚合任务,避免单线程处理慢的问题。

完整代码实现

import openpyxl
from concurrent.futures import ThreadPoolExecutor, as_completed
from tqdm import tqdm
import json

def read_single_sheet(file_path, sheet_name):
    """读取单个工作表,返回结构化数据"""
    # 只读模式+只读取数据,跳过格式等冗余信息
    wb = openpyxl.load_workbook(file_path, read_only=True, data_only=True)
    ws = wb[sheet_name]
    rows_data = []
    # 跳过表头,从第2行开始读取数据
    for row in ws.iter_rows(min_row=2, values_only=True):
        rows_data.append(row)
    wb.close()
    return sheet_name, rows_data

def process_id_batch(id_batch, base_info_map, all_calls_map):
    """批量处理一组id的聚合逻辑"""
    batch_result = []
    for idx in id_batch:
        # 从基础信息字典中获取name和address
        name, address = base_info_map.get(idx, (None, None))
        if not name or not address:
            continue  # 跳过无基础信息的id
        # 整理call日志
        call_logs = [{"call": num} for num in all_calls_map.get(idx, [])]
        # 组装目标格式
        batch_result.append({
            "id": idx,
            "address": address,
            "name": name.title(),  # 首字母大写匹配示例格式
            "log": call_logs
        })
    return batch_result

if __name__ == "__main__":
    excel_path = "your_large_excel_file.xlsx"
    target_sheets = ["A", "work_1", "work_2"]
    
    # 1. 多线程并行读取所有工作表
    print("开始读取工作表...")
    sheet_data_store = {}
    # 线程数设为工作表数量,避免资源浪费
    with ThreadPoolExecutor(max_workers=len(target_sheets)) as executor:
        futures = [executor.submit(read_single_sheet, excel_path, sheet) for sheet in target_sheets]
        # 用tqdm显示读取进度
        for future in tqdm(as_completed(futures), total=len(futures), desc="读取进度"):
            sheet_name, data = future.result()
            sheet_data_store[sheet_name] = data
    
    # 2. 预处理数据,构建映射表
    print("预处理数据...")
    # 构建id到name、address的映射
    base_info_map = {}
    for row in sheet_data_store["A"]:
        idx, name, address = row
        base_info_map[idx] = (name, address)
    
    # 收集所有call记录,按id分组
    all_calls_map = {}
    for sheet_name in ["work_1", "work_2"]:
        for row in sheet_data_store[sheet_name]:
            idx, call_num = row
            if idx not in all_calls_map:
                all_calls_map[idx] = []
            all_calls_map[idx].append(call_num)
    
    # 3. 多线程批量处理id,生成目标JSON
    print("生成目标JSON数据...")
    all_ids = list(base_info_map.keys())
    batch_size = 150  # 根据内存情况调整,内存充足可以调大
    id_batches = [all_ids[i:i+batch_size] for i in range(0, len(all_ids), batch_size)]
    
    final_output = []
    # 线程数根据CPU核数调整,CPU密集型任务建议设为核数一致
    with ThreadPoolExecutor(max_workers=4) as executor:
        futures = [executor.submit(process_id_batch, batch, base_info_map, all_calls_map) for batch in id_batches]
        # 显示处理进度
        for future in tqdm(as_completed(futures), total=len(futures), desc="处理进度"):
            final_output.extend(future.result())
    
    # 4. 保存结果到文件
    with open("final_result.json", "w", encoding="utf-8") as f:
        json.dump(final_output, f, indent=2, ensure_ascii=False)
    
    print(f"处理完成!共生成{len(final_output)}条数据,已保存到final_result.json")

关键优化点说明

  • 只读模式读取:openpyxl的read_only=True会以流式方式读取文件,不加载整个文件到内存,内存占用大幅降低,速度提升明显。
  • 多线程IO读取:并行读取不同工作表,把原本串行的IO等待时间并行化,读取耗时能减少60%以上。
  • 批量线程处理:把id分成小批次处理,既利用了多CPU核心,又避免了单线程处理的瓶颈。
  • 进度可视化:用tqdm实时显示进度,随时掌握任务完成情况。

额外小贴士

  • 如果你的Excel有合并单元格、复杂公式等特殊格式,可以在read_single_sheet函数里做适配,目前的代码完全适配你给出的表结构。
  • 可以根据自己机器的CPU核数调整线程池的max_workers参数:IO密集型任务(读取)可以设为CPU核数的2-4倍,CPU密集型任务(处理)建议设为和核数一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:42:34