Là một lập trình GUI mới và tôi đang cố gắng tạo GUI cho một trong các trình phân tích cú pháp python của tôi.Python & Tkinter -> Giới thiệu về việc gọi một hàm chạy dài đóng băng chương trình
Tôi biết rằng:
Tkinter là đơn ren. Cập nhật màn hình diễn ra trên mỗi chuyến đi qua vòng lặp sự kiện. Bất cứ lúc nào bạn có một lệnh chạy dài, bạn đang ngăn chặn vòng lặp sự kiện hoàn thành một lần lặp, do đó ngăn chặn việc xử lý các sự kiện, do đó ngăn không cho vẽ lại.
Chương trình của tôi gọi hàm lớn mất khoảng 5 phút để chạy hoàn toàn. Vì vậy, tôi đoán giải pháp duy nhất là tu sử dụng thread cho lệnh chạy dài. NHƯNG, lệnh chạy dài của tôi đã được tạo luồng nên tôi không thực sự biết cách tiến hành.
-> Ngay sau khi tôi nhấp vào BUT1 trong GUI, chương trình sẽ đóng băng cho đến khi hàm hoàn tất. Tôi muốn chạy hàm này trong backgroung, vì vậy chương trình sẽ không bị đóng băng.
-> Tôi không tìm kiếm giải pháp hoàn chỉnh nhưng nếu ai đó có thể giúp tôi có một ca khúc tốt, nó sẽ rất tuyệt vời!
- Main.py -> Các GUI
- Module_1.py -> Chức năng mà chúng ta gọi bằng cách nhấp vào nút BUT1
Cảm ơn bạn trước!
Đây là Main.py -> GUI
#!/usr/bin/python
# -*- coding: utf-8 -*-
from Tkinter import *
import sys
import tkMessageBox
import tkFileDialog
import Module_1
import csv
from time import strftime, gmtime
DATE = strftime("_%d_%b_%Y")
class App:
def __init__(self, master):
self.frame = Frame(master, borderwidth=5, relief=RIDGE)
self.frame.grid()
class IORedirector(object):
def __init__(self,TEXT_INFO):
self.TEXT_INFO = TEXT_INFO
class StdoutRedirector(IORedirector):
def write(self,str):
self.TEXT_INFO.config(text=self.TEXT_INFO.cget('text') + str)
self.TEXT_HEADER = self.text_intro = Label(self.frame, bg="lightblue",text="THIS IS \n MY SUPER PROGRAM")
self.TEXT_HEADER.grid(row=0, column=0, columnspan=2, sticky=W+E+N+S)
self.MENU = Frame(self.frame, borderwidth=5, relief=RIDGE, height=12)
self.MENU.grid(row=1, column=0, sticky=N)
self.button = Button(self.MENU, text="QUIT", bg="red", command=self.frame.quit)
self.button.grid(row=4, column=0)
self.BUT1 = Button(self.MENU, text="BUT1", command=self.BUT1)
self.BUT1.grid(row=0, column=0,sticky=W+E)
self.TEXT_INFO = Label(self.frame, height=12, width=40, text="SOME TEXT", bg="grey",borderwidth=5, relief=RIDGE)
self.TEXT_INFO.grid(row=1, column=1, sticky = N+W)
sys.stdout = StdoutRedirector(self.TEXT_INFO)
def BUT1(self):
self.BUT1.config(text="RUNNING")
self.TEXT_INFO.config(text="BUT1 LAUNCHED")
Module_1.main("BUT1")
## HERE WE NEED TO RUN THE FUNCTION
## THE PROGRAMM FREEZE HERE UNTIL THE FUNCTION IS ENTIRELY RUN
self.TEXT_INFO.config(text="BUT1 FINISHED")
self.BUT1.config(text="DONE")
root = Tk()
app = App(root)
root.mainloop()
Và đây là Module_1.py -> chứa hàm lớn
#!/usr/bin/python
# -*- coding: utf-8 -*-
import Queue
import threading
import urllib2
import time
from bs4 import BeautifulSoup as soup
from urllib2 import urlopen
import re
import os
import random
import sys
import logging
import csv
from time import strftime, gmtime
import os
import random
import shutil
import sys
import re
import logging
from threading import RLock
from time import strftime, gmtime
import csv
import urllib
from urllib import urlretrieve
from grab.spider import Spider, Task
logging.basicConfig(level=logging.CRITICAL) # Loggin to DEBUG/INFO
log = logging.getLogger()
DATE = strftime("_%d_%b_%Y")
class SPIDER1(Spider):
initial_urls = ['URL_THAT_I_NEED_TO_PARSE']
def __init__(self):
super(SPIDER1, self).__init__(
thread_number=20,
network_try_limit=20,
task_try_limit=20
)
self.result = {}
def task_initial(self, grab, task):
for opt in grab.css_list("select[name='Template$TestCentreSearch1$SubRegionList'] option")[1:]:
grab.set_input('Template$TestCentreSearch1$SubRegionList', opt.attrib['value'])
grab.submit(extra_post={
'__EVENTTARGET': 'Template$TestCentreSearch1$SubRegionList'
}, make_request=False)
yield Task('parse', grab=grab, country=opt.text_content())
def task_parse(self, grab, task):
log.info('downloaded %s' % task.country)
city_gen = (x.text_content() for x in grab.css_list(".TestCentreSearchLabel+br+span"))
title_gen = (x.text_content() for x in grab.css_list(".TestCentreSearchTitle"))
id_gen = (x.attrib['href'][-36:] for x in grab.css_list(".TestCentreSearchLink"))
for x in zip(city_gen, title_gen, id_gen):
self.result[x[2]] = {
'country': task.country,
'city': x[0],
'name': x[1],
'id': x[2],
'price':'',
'currency':'',
'fee':''
}
yield Task('info', 'URL_URL=%s' % x[2], id=x[2])
def task_info(self, grab, task):
for label in grab.css_list(".TestCentreViewLabel"):
if label.text_content().strip()=="Test Fee:":
fees = label.getnext().text_content().strip()
self.result[task.id]['fee'] = fees
price = re.findall('\d[\d\., ]+\d',fees)
if price:
price = re.findall('\d[\d\., ]+\d',fees)[0]
self.result[task.id]['price'] = price.replace(' ','').replace(',','.')
currency = re.findall('[A-Z]{2,3}[$|€|£]?',fees)
if not currency:
currency = re.findall('[$|€|£]',fees)
if not currency:
currency = fees.replace(price,'').strip().replace(' ','')
if isinstance(currency,list):
currency = currency[0]
self.result[task.id]['currency'] = currency
#log.info(' %(price)s %(currency)s - %(fee)s ' % self.result[task.id])
break
def dump(self, path):
"""
Save result as csv into the path
"""
with open(path, 'w') as file:
file.write("ID;Country;State;City;Name;Price;Currency;Original Fee\n")
for test_center in sorted(self.result.values(), key=lambda x: "%(country)s%(city)s%(name)s" % x):
file.write(("%(id)s;%(country)s;;%(country)s;%(name)s;%(price)s;%(currency)s;%(fee)s\n" % test_center).encode('utf8'))
def main(choice):
parser, path, name = None, None, None
def run(name,parser,path):
log.info('Parsing %s...' % name)
parser.run()
parser.dump(path)
log.info('Parsing %s completed, data was dumped into %s' % (name, path))
log.info(parser.render_stats())
if choice == "NONE":
# DO NOTHING
# HERE I'D LIKE TO HAVE ANOTHER CALL TO ANOTHER THREADED FUNCTION
elif choice == "BUT1":
run('Function1',SPIDER1(),'C:\LOL\Output1'+DATE+'.csv')
Vì vậy, bằng cách nhấp vào BUT1, chúng tôi chạy chức năng chính ("BUT1") chứa trong tệp Module_1.py với đối số BUT1 khởi chạy -> chạy ('Hàm1', SPIDER1(), 'C: \ LOL \ Output1' + DATE + '. csv') Và sau đó là chương trình bị đóng băng cho đến khi trình phân tích cú pháp kết thúc là công việc .. :)
Tôi đã thử điều này nhưng không thành công, tôi khá mới trong việc phân luồng, nếu bạn chỉ có một ví dụ ngắn gọn, nó sẽ rất hữu ích;) –
Bất kỳ ý tưởng nào? Tôi đã thử nhưng không thành công ... Trợ giúp sẽ rất hữu ích;) –