objects gui example buttons python tkinter multiprocessing

python - example - Uso del módulo de multiprocesamiento para actualizar la GUI de Tkinter



tkinter python buttons (2)

He intentado usar el módulo de multiprocesamiento para actualizar la GUI de Tkinter, pero cuando ejecuto este código, me da un error de decapado.

# Test Code for Tkinter with threads import Tkinter from multiprocessing import Queue import multiprocessing import time # Data Generator which will generate Data def GenerateData(): global q for i in range(10): print "Generating Some Data, Iteration %s" %(i) time.sleep(2) q.put("Some Data from iteration %s /n" %(i)) def QueueHandler(): global q, text_wid while True: if not q.empty(): str = q.get() text_wid.insert("end", str) # Main Tkinter Application def GUI(): global text_wid tk = Tkinter.Tk() text_wid = Tkinter.Text(tk) text_wid.pack() tk.mainloop() if __name__ == ''__main__'': # Queue which will be used for storing Data tk = Tkinter.Tk() text_wid = Tkinter.Text(tk) q = multiprocessing .Queue() t1 = multiprocessing.Process(target=GenerateData,args=(q,)) t2 = multiprocessing.Process(target=QueueHandler,args=(q,text_wid)) t1.start() t2.start() text_wid.pack() tk.mainloop()

Error:

PicklingError: Can''t pickle <type ''thread.lock''>: it''s not found as thread.lock

Si text_wid el argumento text_wid , no se informa ningún error, pero el widget de texto no se actualiza con los datos del queque.

ACTUALIZAR:

Modifiqué el código para llamar a la función para actualizar la GUI siempre que haya valor en la cola, evitando así que los widgets Tkinter se pasen a un proceso separado. Ahora, no recibo ningún error, pero el widget no se actualiza con los datos. Sin embargo, si uso la mezcla del módulo de Threading y Multiprocessing , es decir, creo una secuencia separada para manejar los datos de la cola, entonces funciona bien. Mi pregunta por qué no funcionó cuando ejecuto el código del controlador en un proceso separado. ¿No estoy pasando los datos correctamente? A continuación está el código modificado:

# Test Code for Tkinter with threads import Tkinter import multiprocessing from multiprocessing import Queue import time import threading # Data Generator which will generate Data def GenerateData(q): for i in range(10): print "Generating Some Data, Iteration %s" %(i) time.sleep(2) q.put("Some Data from iteration %s /n" %(i)) def QueueHandler(q): while True: if not q.empty(): str = q.get() update_gui(str) #text_wid.insert("end", str) # Main Tkinter Application def GUI(): global text_wid tk = Tkinter.Tk() text_wid = Tkinter.Text(tk) text_wid.pack() tk.mainloop() def update_gui(str): global text_wid text_wid.insert("end", str) if __name__ == ''__main__'': # Queue which will be used for storing Data tk = Tkinter.Tk() text_wid = Tkinter.Text(tk) q = multiprocessing.Queue() t1 = multiprocessing.Process(target=GenerateData,args=(q,)) t2 = multiprocessing.Process(target=QueueHandler,args=(q,)) t1.start() t2.start() text_wid.pack() tk.mainloop()


Te perdiste una parte importante, debes proteger tus llamadas con una trampa __main__ :

if __name__ == ''__main__'': q = Queue.Queue() # Create a thread and run GUI & QueueHadnler in it t1 = multiprocessing.Process(target=GenerateData,args=(q,)) t2 = multiprocessing.Process(target=QueueHandler,args=(q,)) ....

Tenga en cuenta que la cola se pasa como un parámetro en lugar de utilizar un global.

Editar: acaba de detectar otro problema, debe usar Queue del módulo de multiprocessing , no de la Queue :

from multiprocessing import Queue


# Test Code for Tkinter with threads import Tkinter as Tk import multiprocessing from Queue import Empty, Full import time class GuiApp(object): def __init__(self,q): self.root = Tk.Tk() self.root.geometry(''300x100'') self.text_wid = Tk.Text(self.root,height=100,width=100) self.text_wid.pack(expand=1,fill=Tk.BOTH) self.root.after(100,self.CheckQueuePoll,q) def CheckQueuePoll(self,c_queue): try: str = c_queue.get(0) self.text_wid.insert(''end'',str) except Empty: pass finally: self.root.after(100, self.CheckQueuePoll, c_queue) # Data Generator which will generate Data def GenerateData(q): for i in range(10): print "Generating Some Data, Iteration %s" %(i) time.sleep(2) q.put("Some Data from iteration %s /n" %(i)) if __name__ == ''__main__'': # Queue which will be used for storing Data q = multiprocessing.Queue() q.cancel_join_thread() # or else thread that puts data will not term gui = GuiApp(q) t1 = multiprocessing.Process(target=GenerateData,args=(q,)) t1.start() gui.root.mainloop() t1.join() t2.join()