Я полный начинающий Python, пытаясь создать графический интерфейс, который позволяет пользователю выбирать файл Excel, из которого будут извлекаться и анализироваться некоторые данные. Для графического интерфейса я использую tkinter, а для операций Excel я использую openpyxl. Код, который у меня есть в настоящее время, но когда выбранный файл Excel большой, время выполнения глупо длинное (таблица с тысячами столбцов размером в 10 000 строк x 20 заняла около часа, чтобы пройти через итерацию, и время от времени становилось все медленнее). Кроме того, графический интерфейс перестает отвечать на все итерации. Я ранее делал программу практически идентично с помощью 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 полностью функционировать? Должен ли я использовать потоки, чтобы ускорить процесс итерации, или чтобы окно моего графического интерфейса не переходило ко мне "Не реагировать" на меня, пока итерация делает свою вещь?
Я попытался найти вопросы по подобным вопросам, но я действительно не мог найти то, что искал, скорее всего, из-за моего отсутствия возможности поставить свою проблему в правильные слова. Итак, я заранее извиняюсь за то, что задал вопрос, на который, вероятно, ответили миллионы раз. Буду признателен за любую помощь, которую вы могли бы дать, и спасибо за ваше время.
Я работаю над чем-то похожим, но с большими данными.
У меня была аналогичная проблема, и я предполагаю, что это происходит из-за того, что процессор пытается запустить как excel-итерацию, так и root.mainloop() в том же потоке, что не только замедляет процесс, но и зависает ваше приложение, -responsive. Чтобы это правильно работало, вам нужно будет вызвать функцию вашего работника (Iteration) в другом потоке, чем ваш root.mainloop(). Лучший способ сделать это - определить несколько классов для GUI, Worker и App и вызвать потоки функций Worker из вашего класса App, пока ваш графический интерфейс работает в другом цикле.
Простой пример для same-
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()
Что касается итерации по данным, вы можете проверить это для более эффективного кода.
Я не могу написать весь код здесь, поскольку он слишком длинный, поэтому, пожалуйста, обратитесь к ссылкам