我最近开发了一个 python 程序,它读取 csv 文件并在处理它们之后返回包含图形的 pdf。但是,如果 csv 文件很大,则程序会冻结,直到处理完成。使用这种方法:Link,程序不再冻结,而是自动启动而无需按任何按钮。
这是代码:
try:
import Tkinter as tk, time, threading, random, Queue as queue
except ModuleNotFoundError: # Python 3
import tkinter as tk, time, threading, random, queue
class GuiPart(object):
def __init__(self, master, queue):
self.queue = queue
self.button1 = tk.Button(master, text="Command", padx=10,
pady=5, fg="white", bg="#263D42", command=ThreadedClient.worker_thread1)
self.button1.pack()
def processIncoming(self):
while self.queue.qsize():
pass
class ThreadedClient(object):
"""
Launch the main part of the GUI and the worker thread. periodic_call()
and end_application() could reside in the GUI part, but putting them
here means that you have all the thread controls in a single place.
"""
def __init__(self, master):
"""
Start the GUI and the asynchronous threads. We are in the main
(original) thread of the application, which will later be used by
the GUI as well. We spawn a new thread for the worker (I/O).
"""
self.master = master
# Create the queue
self.queue = queue.Queue()
# Set up the GUI part
self.gui = GuiPart(master, self.queue)
# Set up the thread to do asynchronous I/O
# More threads can also be created and used, if necessary
self.running = True
self.thread1 = threading.Thread(target=self.worker_thread1)
self.thread1.start()
# Start the periodic call in the GUI to check the queue
self.periodic_call()
def periodic_call(self):
""" Check every 200 ms if there is something new in the queue. """
self.master.after(200, self.periodic_call)
self.gui.processIncoming()
if not self.running:
# This is the brutal stop of the system. You may want to do
# some cleanup before actually shutting it down.
import sys
sys.exit(1)
def worker_thread1(self):
"""
This is where we handle the asynchronous I/O. For example, it may be
a 'select()'. One important thing to remember is that the thread has
to yield control pretty regularly, be it by select or otherwise.
"""
while self.running:
# To simulate asynchronous I/O, create a random number at random
# intervals. Replace the following two lines with the real thing.
time.sleep(rand.random() * 1.5)
filenames = filedialog.askopenfilenames(initialdir="/", title="Select File", filetypes = (("comma separated file","*.csv"), ("all files", "*.*"))) #ask user to select the file
""" based on the data from csv file I am using matplotlib to draw some graphs and then I export them as pdf """
def end_application(self):
self.running = False # Stops worker_thread1 (invoked by "Done" button).
rand = random.Random()
root = tk.Tk()
client = ThreadedClient(root)
root.mainloop()
如果有人可以通过单击按钮帮助我开始处理,我将不胜感激,因为我想添加更多按钮,调用更多功能。
线程立即启动的原因是因为它在 中__init__
,所以在ThreadedClient
实例化时被调用。
现在您需要一种启动线程的方法,因此我添加了一个名为start_thread1
. 这将创建并启动线程,我们可以从按钮调用此函数。
您需要在ThreadedClient
您已经制作的实例中启动线程。当前,您创建了一个新实例,但这将不起作用,因为您想使用已有的实例 ( client
)。因此,您需要在GuiPart
. 我叫过它client_instance
。
然后您可以使用命令启动线程client_instance.start_thread1
。程序的其余部分不变。
class GuiPart(object):
def __init__(self, master, queue, client_instance):
self.queue = queue
self.button1 = tk.Button(master, text="Command", padx=10,
pady=5, fg="white", bg="#263D42", command=client_instance.start_thread1)
self.button1.pack()
def processIncoming(self):
while self.queue.qsize():
pass
class ThreadedClient(object):
"""
Launch the main part of the GUI and the worker thread. periodic_call()
and end_application() could reside in the GUI part, but putting them
here means that you have all the thread controls in a single place.
"""
def __init__(self, master):
"""
Start the GUI and the asynchronous threads. We are in the main
(original) thread of the application, which will later be used by
the GUI as well. We spawn a new thread for the worker (I/O).
"""
self.master = master
# Create the queue
self.queue = queue.Queue()
self.running = True
# Set up the GUI part
self.gui = GuiPart(master, self.queue, self)
# Start the periodic call in the GUI to check the queue
self.periodic_call()
def start_thread1(self):
# Set up the thread to do asynchronous I/O
# More threads can also be created and used, if necessary
thread1 = threading.Thread(target=self.worker_thread1)
thread1.start()
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句