我是一名完全的Python初学者,试图制作一个允许用户选择一个Excel文件的GUI,从中可以提取和分析一些数据。对于GUI,我正在使用tkinter,对于Excel操作,我正在使用openpyxl。 我当前拥有的代码有效,但是当选择的Excel文件很大时,运行时就很长(10,000行x 20列电子表格需要大约一个小时才能遍历,随着时间的流逝,速度变慢了) 。同样,GUI在迭代过程中也停止响应。我以前使用MATLAB制作了几乎完全相同的程序,并且效果很好,整个迭代过程仅需一到两秒钟,因此肯定很有趣这里。现在我知道这是我的问题,而不是Python的问题,所以我希望你们能帮助我指出正确的解决方法。
以下是一些我正在使用的简化示例,以帮助说明我的处境。我需要遍历电子表格的每一行,检查该行中的某个值以查看它是否与我想要的匹配,如果匹配,我存储该行中的一些数据。
wb = openpyxl.load_workbook(filename = 'some_garbage.xlsx', read_only=True).worksheets[0]
all_data = wb.cell
desiredColor = 'Purple'
foodStorage = []
for row in range(2, wb.max_row + 1):
print(row)
if(all_data(row, 1).value == desiredColor):
foodStorage.append(all_data(row,2))
print('I found purple! Yee')
我应该使用openpyxl以外的其他模块来执行此任务,还是我只是在犯一些使openpyxl无法充分发挥作用的错误? 我应该使用线程来加快迭代过程,还是要确保在迭代过程中我的GUI窗口不会对我产生全部“不响应”?
我试图搜索有关类似问题的问题,但实际上并不能找到我想要的东西,这很可能是由于我缺乏将问题用恰当的语言表达的能力。因此,对于可能要回答一百万遍的问题,我事先深表歉意。感谢您能提供的任何帮助,并感谢您的宝贵时间。
答案 0 :(得分:-1)
我正在研究类似的东西,但是数据更大。
我有一个类似的问题,我认为它的发生是因为处理器试图在同一线程上同时运行excel迭代和root.mainloop(),这不仅减慢了进程,而且使应用程序挂起GUI无响应。为了使其正常工作,您必须在与root.mainloop()不同的线程中调用worker(Iteration)函数。最好的方法是为GUI,Worker和App定义多个类,并在GUI在不同循环中运行时从App类中调用Worker函数线程。
相同的简单示例-
import tkinter as tk
from tkinter import ttk,messagebox
import threading
import time
#base GUI Class
class GUI:
def __init__(self, root, runCommand):
mf = ttk.Frame(root, padding="5 5 5 5")
mf.grid(column=0, row=0)
mf.columnconfigure(0, weight=1)
mf.rowconfigure(0, weight=1)
# Global Values
self.Fnm = tk.StringVar(root, "SearchFile.xlsx")
self.Ncol = tk.StringVar(root, "D")
self.Vcol = tk.StringVar(root, "C")
# Label
tk.Label(mf, text="File Name").grid(column=1, row=1, pady=6)
tk.Label(mf, text="Name Col").grid(column=1, row=3, pady=6)
tk.Label(mf, text="Value Col").grid(column=3, row=3, pady=6)
# components
self.fname = ttk.Entry(mf, width=18, textvariable=self.Fnm)
self.nmCol = ttk.Entry(mf, width=6, textvariable=self.Ncol)
self.valCol = ttk.Entry(mf, width=6, textvariable=self.Vcol)
self.but = ttk.Button(mf, text="Refresh", command=runCommand)
self.pgbar = ttk.Progressbar(mf, orient="horizontal", mode="determinate")
# Design
self.fname.grid(column=2, row=1, pady=3, columnspan=3)
self.nmCol.grid(column=2, row=3, pady=3)
self.valCol.grid(column=4, row=3, pady=3)
self.but.grid(column=2, row=2, columnspan=2)
self.pgbar.grid(column=1,row=4,columnspan=4)
def refresh(self):
pass
def get(self):
return [self.Fnm.get(), self.Ncol.get(), self.Vcol.get()]
#Base process Class
class Proc:
def __init__(self, dets,pgbar,but):
self.Fnm = dets[0]
self.Ncol = dets[1]
self.Vcol = dets[2]
self.pg=pgbar
self.butt=but
def refresh(self):
self.butt['state'] = 'disabled'
self.pg.start()
#ATTENTION:Enter Your process Code HERE
for _ in range(5):
time.sleep(2)#Longggg work
self.pg.stop()
#Any search/sort algorithm to be used
#You can use self.pg.step() to be more specific for how the progress bar proceeds
messagebox.showinfo("Process Done","Success")
self.butt['state'] = 'enabled'
#Base Application Class
class App:
def __init__(self, master):
self.master = master
self.gui = GUI(self.master, self.runit)
def runit(self):
self.search = Proc(self.gui.get(),self.gui.pgbar,self.gui.but)
self.thread1 = threading.Thread(target=self.search.refresh)
self.thread1.start()
def main():
app = tk.Tk()
gui = App(app)
app.title("Refresh Search File")
app.mainloop()
if __name__ == '__main__':
main()
关于数据迭代,您可以检出this以获得更有效的代码。
我不能在此处编写所有代码,因为它太长了,所以请参考链接