openpyxl 在只读模式下真的很慢!!我怎样才能改进我的脚本?
openpyxl is really slow in read only mode!! how can I improve my script?
我写了一个简单的例子。此脚本读取一个 excel 文件并仅从中复制第一列中包含列表 "ls" 中指定的字符串之一的行。复制的行将粘贴到另一个 excel 文件中。在我的代码下方:
from datetime import datetime
import openpyxl
print("Current Time =", datetime.now().strftime("%H:%M:%S"))
src_wb = openpyxl.load_workbook("C:\Users\Admin\Desktop\database.xlsx")
print("Current Time =", datetime.now().strftime("%H:%M:%S"))
print("\n\n")
src_ws = src_wb[src_wb.sheetnames[0]]
dst_wb = openpyxl.Workbook()
dst_ws = dst_wb.active
dst_ws.title = "TEST"
dst_row_id, src_row_id = 0, 0
ls = ["ciao", "hola", "hello"]
my_column_id = 1
for row in src_ws.rows:
src_row_id += 1
#print("Current Time =", datetime.now().strftime("%H:%M:%S"))
for element in ls:
if src_ws.cell(src_row_id, my_column_id).value == element:
dst_row_id += 1
dst_column_id = 0
for cell in row:
dst_column_id += 1
dst_cell = dst_ws.cell(dst_row_id,column=dst_column_id)
dst_cell.value = cell.value
break
dst_wb.save("test.xlsx")
dst_wb.close()
下面的输出:
λ python stack.py
Current Time = 19:36:38
Current Time = 19:37:20 <- after this point the script is quite fast
这段代码运行良好,但是当我的源 excel 文件很重时,指令 src_wb = openpyxl.load_workbook("C:\Users\Admin\Desktop\database.xlsx")
需要很多次。在我的示例中,"database.xlsx" 文件有 177137 行 和 14 列 。打开它,openpyxl 需要 42 秒,但是当它必须读取行时,它似乎相当快。
为了改善这种情况我尝试使用 "read only" 模式 (openpyxl.load_workbook("C:\Users\Admin\Desktop\database.xlsx", read_only = True
) 但是这样脚本变得太慢了..它可以快速打开 "database.xlsx" 文件, 但在 "copy and paste" 中非常慢(它太慢了,完成任务需要几个小时!)请参见下面的输出:
λ python stack.py
Current Time = 19:37:47
Current Time = 19:37:52 <-- after this point the script is very slow
如何提高只读模式下的脚本性能?或者以另一种方式,我不知道..根据您的经验,改进我的代码的最佳解决方案是什么?
@Daniel Ocando:我的 excel 文件由简单的字符串组成。下面是一个例子:
您提供的代码具有三个嵌套的 for 循环(这通常意味着代码具有 O(n3)
时间复杂度)。我设法删除了一个 for 循环,因此将时间复杂度降低到 O(n2)
.
您可以利用 sets are generally faster than lists regarding membership tests 并将 ls = ["ciao", "hola", "hello"]
列表更改为 set
。
最后,您可以利用 write_only mode 来尝试使写入速度更快。
考虑到单元格只包含一个带有简单单词的字符串,您可以尝试以下代码并检查性能是否有所提高:
from datetime import datetime
import openpyxl
def get_list(row):
list_for_row_values = []
for cell in row:
list_for_row_values.append(cell.value)
return list_for_row_values
print("Current Time =", datetime.now().strftime("%H:%M:%S"))
src_wb = openpyxl.load_workbook("C:\Users\Admin\Desktop\database.xlsx", read_only=True)
print("Current Time =", datetime.now().strftime("%H:%M:%S"))
print("\n\n")
src_ws = src_wb[src_wb.sheetnames[0]]
dst_wb = openpyxl.Workbook(write_only=True)
dst_ws = dst_wb.create_sheet()
ls = ("ciao", "hola", "hello")
for row in src_ws.rows:
if(row[0].value) in ls:
list_for_row_values = get_list(row)
dst_ws.append(list_for_row_values)
dst_wb.save("test.xlsx")
我写了一个简单的例子。此脚本读取一个 excel 文件并仅从中复制第一列中包含列表 "ls" 中指定的字符串之一的行。复制的行将粘贴到另一个 excel 文件中。在我的代码下方:
from datetime import datetime
import openpyxl
print("Current Time =", datetime.now().strftime("%H:%M:%S"))
src_wb = openpyxl.load_workbook("C:\Users\Admin\Desktop\database.xlsx")
print("Current Time =", datetime.now().strftime("%H:%M:%S"))
print("\n\n")
src_ws = src_wb[src_wb.sheetnames[0]]
dst_wb = openpyxl.Workbook()
dst_ws = dst_wb.active
dst_ws.title = "TEST"
dst_row_id, src_row_id = 0, 0
ls = ["ciao", "hola", "hello"]
my_column_id = 1
for row in src_ws.rows:
src_row_id += 1
#print("Current Time =", datetime.now().strftime("%H:%M:%S"))
for element in ls:
if src_ws.cell(src_row_id, my_column_id).value == element:
dst_row_id += 1
dst_column_id = 0
for cell in row:
dst_column_id += 1
dst_cell = dst_ws.cell(dst_row_id,column=dst_column_id)
dst_cell.value = cell.value
break
dst_wb.save("test.xlsx")
dst_wb.close()
下面的输出:
λ python stack.py
Current Time = 19:36:38
Current Time = 19:37:20 <- after this point the script is quite fast
这段代码运行良好,但是当我的源 excel 文件很重时,指令 src_wb = openpyxl.load_workbook("C:\Users\Admin\Desktop\database.xlsx")
需要很多次。在我的示例中,"database.xlsx" 文件有 177137 行 和 14 列 。打开它,openpyxl 需要 42 秒,但是当它必须读取行时,它似乎相当快。
为了改善这种情况我尝试使用 "read only" 模式 (openpyxl.load_workbook("C:\Users\Admin\Desktop\database.xlsx", read_only = True
) 但是这样脚本变得太慢了..它可以快速打开 "database.xlsx" 文件, 但在 "copy and paste" 中非常慢(它太慢了,完成任务需要几个小时!)请参见下面的输出:
λ python stack.py
Current Time = 19:37:47
Current Time = 19:37:52 <-- after this point the script is very slow
如何提高只读模式下的脚本性能?或者以另一种方式,我不知道..根据您的经验,改进我的代码的最佳解决方案是什么?
@Daniel Ocando:我的 excel 文件由简单的字符串组成。下面是一个例子:
您提供的代码具有三个嵌套的 for 循环(这通常意味着代码具有 O(n3)
时间复杂度)。我设法删除了一个 for 循环,因此将时间复杂度降低到 O(n2)
.
您可以利用 sets are generally faster than lists regarding membership tests 并将 ls = ["ciao", "hola", "hello"]
列表更改为 set
。
最后,您可以利用 write_only mode 来尝试使写入速度更快。
考虑到单元格只包含一个带有简单单词的字符串,您可以尝试以下代码并检查性能是否有所提高:
from datetime import datetime
import openpyxl
def get_list(row):
list_for_row_values = []
for cell in row:
list_for_row_values.append(cell.value)
return list_for_row_values
print("Current Time =", datetime.now().strftime("%H:%M:%S"))
src_wb = openpyxl.load_workbook("C:\Users\Admin\Desktop\database.xlsx", read_only=True)
print("Current Time =", datetime.now().strftime("%H:%M:%S"))
print("\n\n")
src_ws = src_wb[src_wb.sheetnames[0]]
dst_wb = openpyxl.Workbook(write_only=True)
dst_ws = dst_wb.create_sheet()
ls = ("ciao", "hola", "hello")
for row in src_ws.rows:
if(row[0].value) in ls:
list_for_row_values = get_list(row)
dst_ws.append(list_for_row_values)
dst_wb.save("test.xlsx")