heiyahua 发表于 2023-6-9 10:18

求助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('拆分完成!')

ifdess 发表于 2023-6-9 11:27

在处理较大的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文件的效率。记得在实施这些改进之前,对代码进行备份,以防意外情况发生。

longteng9421 发表于 2023-6-9 11:51

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('拆分完成!')

heiyahua 发表于 2023-6-9 14:59

ifdess 发表于 2023-6-9 11:27
在处理较大的Excel文件时,可以尝试以下几个优化方法:

1. 逐步读取数据:使用`pd.read_excel`函数时, ...

多谢指导:lol

heiyahua 发表于 2023-6-9 15:44

longteng9421 发表于 2023-6-9 11:51
import os
import pandas as pd
import logging


多谢修改!!

law.liu 发表于 2023-6-9 18:07

我在这里使用多线程提高速度的方法,但具体的性能提升取决于你电脑的配置和数据集的大小。
代码修改如下“”
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('拆分完成!')

一闪一闪233 发表于 2023-6-10 03:39

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('拆分完成!')

zpy2 发表于 2023-6-10 07:13

golang excelize有个流式读取,可以试试
页: [1]
查看完整版本: 求助python代码拆分excel另存为csv运行速度太慢