如何用进程池替换For循环实现多进程写入XLSX文件?
问题:用多进程加速XlsxWriter写入Excel失败
我用Pandas读取大型CSV文件,再通过XLSXWriter写入Excel生成数据图表。原代码是单循环写入,想改成进程池提速,但运行报错。
原单线程写入代码
workbook = xlsxwriter.Workbook(excel_file_path, {"nan_inf_to_errors": True, "strings_to_numbers": True}) data_worksheet = workbook.add_worksheet() Data_chart = workbook.add_worksheet("Charts") for column_num, column_name in enumerate(data): data_worksheet.write(0,column_num,column_name) data_worksheet.write_column(1, column_num, data[column_name])
尝试的多进程报错代码
# 获取CSV列数 with open(path1, 'r') as csv1: first_line = csv1.readline() ncol = first_line.count(';') + 1 print("number of columns is: " + str(ncol)) # 初始化Workbook和工作表 workbook = xlsxwriter.Workbook(excel_file_path, {"nan_inf_to_errors": True, "strings_to_numbers": True}) data_worksheet = workbook.add_worksheet() Data_chart = workbook.add_worksheet("Charts") # 定义要映射到进程池的函数 ncol1 = range(ncol) def data_transfer(): for column_num, column_name in enumerate(data): data_worksheet.write(0,column_num,column_name) data_worksheet.write_column(1, column_num, data[column_name]) if __name__ == '__main__': with Pool(processes=4) as pool: pool_transfer = pool.map(data_transfer, ncol1) pool.close pool.join
为啥你的多进程代码会报错?
- XlsxWriter不支持跨进程共享:
Workbook和Worksheet是单进程独占对象,多个进程同时写入会直接导致文件损坏或逻辑冲突,这是XlsxWriter的设计限制。 - 进程池用法错误:
pool.map要求传入的函数必须接受一个参数,但你的data_transfer没有参数;而且每个进程都会执行完整的写入循环,等于重复写了N次数据,完全不符合预期。 - 场景选错了:写入Excel是磁盘IO密集型任务,多进程反而会因为进程间通信、磁盘竞争拖慢速度,甚至不如单进程高效。
该怎么优化才对?
1. 用Pandas内置的Excel写入(最推荐)
Pandas和XlsxWriter有原生集成,内部已经做了批量写入优化,比手动循环快N倍,代码还更简洁:
import pandas as pd # 读取CSV(大文件可以加chunksize分块,但写入时会自动合并) data = pd.read_csv(path1, sep=';') # 用XlsxWriter作为引擎写入Excel with pd.ExcelWriter(excel_file_path, engine='xlsxwriter', options={"nan_inf_to_errors": True, "strings_to_numbers": True}) as writer: # 直接写入整个DataFrame,自动处理表头和数据 data.to_excel(writer, sheet_name='Data', index=False) # 获取Workbook和工作表对象,用于后续生成图表 workbook = writer.book data_worksheet = writer.sheets['Data'] chart_worksheet = workbook.add_worksheet("Charts") # 在这里添加你的图表生成逻辑即可
2. 手动优化单进程逻辑(如果必须自己写)
如果一定要手动处理写入,重点是减少循环中的IO操作:
- 避免逐列调用
write_column,尽量批量处理(但Pandas的to_excel已经帮你做了这件事) - 确保CSV读取时指定正确的分隔符(你用了
;,别忘在pd.read_csv里加sep=';')
3. 多进程只用来处理数据,不是写入
如果是数据预处理阶段(比如清洗、计算每列数据),可以用多进程处理,处理完再单进程写入:
from multiprocessing import Pool import pandas as pd def process_column(column_data): # 这里写列数据的预处理逻辑,比如清洗、转换、计算 # 示例:把字符串列转成大写 if column_data.dtype == 'object': return column_data.str.upper() return column_data if __name__ == '__main__': # 读取原始数据 data = pd.read_csv(path1, sep=';') # 把每列数据拆成列表,供进程池处理 columns_list = [data[col] for col in data.columns] # 多进程处理数据 with Pool(processes=4) as pool: processed_columns = pool.map(process_column, columns_list) # 处理完后,单进程写入Excel with pd.ExcelWriter(excel_file_path, engine='xlsxwriter', options={"nan_inf_to_errors": True, "strings_to_numbers": True}) as writer: # 把处理后的列重新组合成DataFrame processed_data = pd.DataFrame({col: processed_columns[i] for i, col in enumerate(data.columns)}) processed_data.to_excel(writer, sheet_name='Data', index=False) # 后续添加图表逻辑
内容的提问来源于stack exchange,提问作者Yetti
相关产品推荐
相关产品推荐

