求助python代码拆分excel另存为csv运行速度太慢
本帖最后由 heiyahua 于 2023-6-9 10:29 编辑代码如下,在处理较大的excel文件时,代码运行特别耗时间,求助大佬们帮忙给点建议,谢谢。
import os
import pandas as pd
import logging
import time
from concurrent.futures import ThreadPoolExecutor
# 获取当前文件夹路径
current_dir = os.getcwd()
# 获取当前文件夹内的所有Excel文件
excel_files =
# 设置openpyxl日志级别为ERROR,忽略Workbook无默认样式的告警
logging.getLogger('openpyxl').setLevel(logging.ERROR)
# 设置pandas不输出警告信息
pd.options.mode.chained_assignment = None# 取消chained_assignment警告
pd.options.mode.use_inf_as_na = True# 将inf视为缺失值,避免警告输出
# 定义处理Excel文件的函数
def process_excel(excel_file):
# 创建以Excel文件命名的文件夹
excel_folder = os.path.splitext(excel_file)
if not os.path.exists(excel_folder):
os.makedirs(excel_folder)
# 读取Excel文件中的sheet名
excel = pd.ExcelFile(excel_file)
sheet_names = excel.sheet_names
# 初始化上一个保存文件的时间
prev_time = time.time()
# 遍历每个sheet,将第三行及以下的内容保存为CSV文件
for sheet_name in sheet_names:
# 读取Excel文件中的每个sheet,跳过前两行
df_sheet = pd.read_excel(excel_file, sheet_name=sheet_name, skiprows=2, engine='openpyxl')
# 将sheet名作为文件名,保存为CSV文件
csv_file_name = os.path.join(excel_folder, f'{sheet_name}.csv')
df_sheet.to_csv(csv_file_name, index=False,encoding='gbk')
# 计算并打印保存文件所使用的时间
current_time = time.time()
elapsed_time = current_time - prev_time
print(f'Saved {csv_file_name} successfully. Elapsed time: {elapsed_time:.2f} seconds')
prev_time = current_time
# 使用多线程处理Excel文件
with ThreadPoolExecutor(max_workers=16) as executor:# 可根据需要设置最大线程数
executor.map(process_excel, excel_files)
print('拆分完成!')
在处理较大的Excel文件时,可以尝试以下几个优化方法:
1. 逐步读取数据:使用`pd.read_excel`函数时,可以指定`chunksize`参数来逐步读取数据,而不是一次性读取整个文件。这样可以减少内存的使用,并且降低整体的运行时间。例如,可以将`pd.read_excel(excel_file, sheet_name=sheet_name, skiprows=2, engine='openpyxl')`修改为`pd.read_excel(excel_file, sheet_name=sheet_name, skiprows=2, engine='openpyxl', chunksize=1000)`,并在处理每个chunk时逐步处理数据。
2. 并行处理:使用多线程或多进程来并行处理多个Excel文件。你已经使用了`ThreadPoolExecutor`来实现多线程处理,可以通过增加`max_workers`参数的值来增加线程数,以加快处理速度。请注意,线程数并不是越多越好,具体最佳值取决于你的系统配置和处理的Excel文件数量。
3. 优化写入文件:在当前代码中,每个线程都会将处理后的数据写入独立的CSV文件。写入文件可能会成为性能瓶颈,特别是当文件数量较大时。你可以尝试将数据保存在内存中,而不是写入磁盘,直到所有数据处理完成后再统一写入磁盘。可以使用`StringIO`或`BytesIO`来创建内存文件对象,并将数据写入该对象,最后再将整个对象一次性写入磁盘。
4. 优化循环逻辑:遍历每个sheet时,你可以尝试减少不必要的操作。例如,可以将保存文件的时间记录放在循环外部,而不是每次循环内部计算。这样可以减少不必要的时间开销。
尝试应用上述优化方法,可以提高处理较大Excel文件的效率。记得在实施这些改进之前,对代码进行备份,以防意外情况发生。 import os
import pandas as pd
import logging
import time
from concurrent.futures import ThreadPoolExecutor
# 获取当前文件夹路径
current_dir = os.getcwd()
# 获取当前文件夹内的所有Excel文件
excel_files =
# 设置openpyxl日志级别为ERROR,忽略Workbook无默认样式的告警
logging.getLogger('openpyxl').setLevel(logging.ERROR)
# 设置pandas不输出警告信息
pd.options.mode.chained_assignment = None# 取消chained_assignment警告
pd.options.mode.use_inf_as_na = True# 将inf视为缺失值,避免警告输出
# 定义处理Excel文件的函数
def process_excel(excel_file):
# 创建以Excel文件命名的文件夹
excel_folder = os.path.splitext(excel_file)
if not os.path.exists(excel_folder):
os.makedirs(excel_folder)
# 读取Excel文件中的sheet名
excel = pd.ExcelFile(excel_file)
sheet_names = excel.sheet_names
# 初始化上一个保存文件的时间
prev_time = time.time()
# 遍历每个sheet,将第三行及以下的内容保存为CSV文件
for sheet_name in sheet_names:
# 读取Excel文件中的每个sheet,跳过前两行
df_sheet = pd.read_excel(excel_file, sheet_name=sheet_name, skiprows=2, engine='openpyxl')
# 将sheet名作为文件名,保存为CSV文件
csv_file_name = os.path.join(excel_folder, f'{sheet_name}.csv')
df_sheet.to_csv(csv_file_name, index=False, encoding='gbk')
# 计算并打印保存文件所使用的时间
current_time = time.time()
elapsed_time = current_time - prev_time
print(f'Saved {csv_file_name} successfully. Elapsed time: {elapsed_time:.2f} seconds')
prev_time = current_time
# 使用多线程处理Excel文件
with ThreadPoolExecutor(max_workers=16) as executor:# 可根据需要设置最大线程数
executor.map(process_excel, excel_files)
print('拆分完成!')
ifdess 发表于 2023-6-9 11:27
在处理较大的Excel文件时,可以尝试以下几个优化方法:
1. 逐步读取数据:使用`pd.read_excel`函数时, ...
多谢指导:lol longteng9421 发表于 2023-6-9 11:51
import os
import pandas as pd
import logging
多谢修改!! 我在这里使用多线程提高速度的方法,但具体的性能提升取决于你电脑的配置和数据集的大小。
代码修改如下“”
import os
import pandas as pd
import logging
import time
from concurrent.futures import ThreadPoolExecutor
import dask.dataframe as dd
# 获取当前文件夹路径
current_dir = os.getcwd()
# 获取当前文件夹内的所有Excel文件
excel_files =
# 设置openpyxl日志级别为ERROR,忽略Workbook无默认样式的告警
logging.getLogger('openpyxl').setLevel(logging.ERROR)
# 设置pandas不输出警告信息
pd.options.mode.chained_assignment = None# 取消chained_assignment警告
pd.options.mode.use_inf_as_na = True# 将inf视为缺失值,避免警告输出
# 定义处理Excel文件的函数
def process_excel(excel_file):
# 创建以Excel文件命名的文件夹
excel_folder = os.path.splitext(excel_file)
if not os.path.exists(excel_folder):
os.makedirs(excel_folder)
# 读取Excel文件中的sheet名
excel = pd.ExcelFile(excel_file)
sheet_names = excel.sheet_names
# 遍历每个sheet,将第三行及以下的内容保存为CSV文件
for sheet_name in sheet_names:
# 读取Excel文件中的每个sheet,选择需要读取的列
df_sheet = pd.read_excel(excel_file, sheet_name=sheet_name, usecols=lambda x: x not in range(2), engine='openpyxl')
# 将sheet名作为文件名,保存为CSV文件
csv_file_name = os.path.join(excel_folder, f'{sheet_name}.csv')
df_sheet.to_csv(csv_file_name, index=False, encoding='gbk')
print(f'Saved {csv_file_name} successfully.')
# 使用多线程处理Excel文件
with ThreadPoolExecutor(max_workers=16) as executor:
executor.map(process_excel, excel_files)
print('拆分完成!')
import os
import pandas as pd
import time
from concurrent.futures import ThreadPoolExecutor
# 获取当前文件夹路径
current_dir = os.getcwd()
# 获取当前文件夹内的所有Excel文件
excel_files =
# 设置pandas不输出警告信息
pd.options.mode.chained_assignment = None# 取消chained_assignment警告
pd.options.mode.use_inf_as_na = True# 将inf视为缺失值,避免警告输出
# 定义处理Excel文件的函数
def process_excel_sheet(args):
excel_file, sheet_name = args
# 创建以Excel文件命名的文件夹
excel_folder = os.path.splitext(excel_file)
if not os.path.exists(excel_folder):
os.makedirs(excel_folder)
# 读取Excel文件中的每个sheet,跳过前两行
df_sheet = pd.read_excel(excel_file, sheet_name=sheet_name, skiprows=2, engine='openpyxl')
# 将sheet名作为文件名,保存为CSV文件
csv_file_name = os.path.join(excel_folder, f'{sheet_name}.csv')
df_sheet.to_csv(csv_file_name, index=False, encoding='gbk')
print(f'Saved {csv_file_name} successfully.')
# 创建处理任务列表
tasks = []
for excel_file in excel_files:
# 读取Excel文件中的sheet名
excel = pd.ExcelFile(excel_file)
sheet_names = excel.sheet_names
for sheet_name in sheet_names:
tasks.append((excel_file, sheet_name))
# 使用多线程处理Excel文件中的每个sheet
with ThreadPoolExecutor(max_workers=16) as executor:# 可根据需要设置最大线程数
executor.map(process_excel_sheet, tasks)
print('拆分完成!')
golang excelize有个流式读取,可以试试
页:
[1]