Python openpyxl在只读模式下速度非常慢!!如何改进我的脚本?

Python openpyxl在只读模式下速度非常慢!!如何改进我的脚本?,python,openpyxl,Python,Openpyxl,我写了一个简单的例子。此脚本读取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\\da

我写了一个简单的例子。此脚本读取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文件由简单的字符串组成。下面是一个例子:


您提供的代码有三个嵌套的for循环(这通常意味着代码具有
O(n3)
时间复杂度)。我设法删除了一个for循环,因此将时间复杂度降低到
O(n2)

您可以利用这一点,并且可以将
ls=[“ciao”、“hola”、“hello”]
列表更改为
集合

最后,您可以利用这个优势,尝试使书写速度更快

考虑到单元格仅包含一个包含简单单词的字符串,您可以尝试以下代码并检查性能是否有所提高:

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")

您提供的代码有三个嵌套for循环(这通常意味着代码具有
O(n3)
时间复杂性)。我设法删除了一个for循环,因此将时间复杂度降低到
O(n2)

您可以利用这一点,并且可以将
ls=[“ciao”、“hola”、“hello”]
列表更改为
集合

最后,您可以利用这个优势,尝试使书写速度更快

考虑到单元格仅包含一个包含简单单词的字符串,您可以尝试以下代码并检查性能是否有所提高:

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文件的示例吗?#Daniel Ocando,我的“database.xlsx”文件由简单的字符串组成,没有什么特别之处。请参阅我随附的屏幕截图(这只是一个示例)。只读模式的问题是因为您没有按照建议使用。文件中单元格的上下文是什么?您介意展示一下Excel文件的示例吗?#Daniel Ocando,我的“database.xlsx”文件由简单的字符串组成,没有什么特别之处。请参阅我随附的屏幕截图(这只是一个示例)。只读模式的问题是因为您没有按照建议使用它。@Daniel Ocando:Whoo Daniel,它能工作!我刚刚用你的代码修改了我的真实代码,看起来效果不错。我还添加了一个缓存,以防止添加重复的行(这只是一个简单的字典)。我对openpyxl了解不多,但我的代码和你的代码之间的主要区别似乎是选择通过“append”方法而不是“cell”方法来编写。可能在“只读”模式下,“单元格”方法存在一些性能问题。Daniel,我想知道,在您的代码中,是否也可以复制单元格样式?如果不影响性能,最好也添加此功能。您需要使用copy()模块。在另一个列表中查找所有信息。关于集合比列表更快进行包容检查的观点仅在理论上有效,几乎肯定与此无关——这是一种良好的做法,但也是过早的优化。@Daniel Ocando:哇,Daniel,它行得通!我刚刚用你的代码修改了我的真实代码,看起来效果不错。我还添加了一个缓存,以防止添加重复的行(这只是一个简单的字典)。我对openpyxl了解不多,但我的代码和你的代码之间的主要区别似乎是选择通过“append”方法而不是“cell”方法来编写。可能在“只读”模式下,“单元格”方法存在一些性能问题。Daniel,我想知道,在您的代码中,是否也可以复制单元格样式?如果不影响性能,最好也添加此功能。您需要使用copy()模块。在另一个列表中找到所有信息。关于集合比列表更快进行包容检查的观点仅在理论上有效,几乎肯定与此无关——这是一种良好的做法,但也是过早的优化。