Python Forum
[Tkinter] Updating Tkinter label using multiprocessing
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] Updating Tkinter label using multiprocessing
#1
Hi!
I'm having trouble updating a label depending on a result from a function from one of the two processes I'm running. I'm trying using Queues, but can't make it work.

This is a simplified example of the code:

import multiprocessing as mp
from tkinter import DISABLED, NORMAL, Label, LabelFrame, Tk
import queue

class Gui(object):
    def __init__(self, q):
        self.root = Tk()
        self.root.geometry('150x100')

        self.frameP1 = LabelFrame(self.root, text="Process1", font=("Helvetica", 14, "bold"), bd=0)
        self.frameP1.pack(padx=12)
        self.currentUserProcess1 = Label(self.frameP1, text="Current User p1", font=("Helvetica", 10, "bold"))
        self.currentUserProcess1.pack()
        
        self.frameP2 = LabelFrame(self.root, text="Process2", font=("Helvetica", 14, "bold"), bd=0)
        self.frameP2.pack()
        self.currentUserProcess2 = Label(self.frameP2, text="Current User p2", font=("Helvetica", 10, "bold"))
        self.currentUserProcess2.pack()
        self.root.after(100,self.CheckQueuePoll,q)
    

    def CheckQueuePoll(self, c_queue):
        try:
            str = c_queue(0)
            self.currentUserProcess2.configure(text=str)
        except queue.Empty:
            pass
        finally:
            self.root.after(100, self.CheckQueuePoll, q)

def process1():
    print("Executing process1")
    
    #doSomething

def process2():
    print("Executing process2")
    log = "Current User Process 2"
    q.put(log)

def startProcesses():
    global p1
    global p2
    p1 = mp.Process(target = process1)
    p2 = mp.Process(target = process2)
    p1.start()
    p2.start()


def stopProcesses():
    p1.terminate()
    p2.terminate()
       
if __name__ == '__main__':
    q = mp.Queue()
    gui = Gui(q)
    p1 = mp.Process(target = process1, args=(q,))
    p2 = mp.Process(target = process2, args=(q,))
    p1.start()
    p2.start()
    gui.root.mainloop()
This is giving me this error:
Error:
TypeError: 'Queue' object is not callable
This happens when trying to execute "str = c_queue(0)" on CheckQueuePoll function.
I tried different ways of importing Queue, but I always get errors. I'd appreciate any help or hint in what I'm doing wrong.
Thanks in advance!
Reply
#2
The object c_queue is not callable. Try this perhaps
    def CheckQueuePoll(self, c_queue):
        try:
            str = c_queue.get_nowait()
            c_queue.task_done()
            self.currentUserProcess2.configure(text=str)
        except queue.Empty:
            pass
        finally:
            self.root.after(100, self.CheckQueuePoll, q)
Reply
#3
Pass gui.currentUserProcess 1 or 2 to the process as an arg. Each process can then update it.
Reply
#4
(Aug-12-2022, 02:37 PM)Gribouillis Wrote: The object c_queue is not callable. Try this perhaps
    def CheckQueuePoll(self, c_queue):
        try:
            str = c_queue.get_nowait()
            c_queue.task_done()
            self.currentUserProcess2.configure(text=str)


        except queue.Empty:
            pass
        finally:
            self.root.after(100, self.CheckQueuePoll, q)

I tried it but now it gives me this errors:
Error:
TypeError: process1() takes 0 positional arguments but 1 was given
Error:
TypeError: process2() takes 0 positional arguments but 1 was given
So I tried passing the "q" as an argument to process1() and process2() and now I have this error:
Error:
AttributeError: 'Queue' object has no attribute 'task_done'
There is maybe a problem with the import? I tried importing queue in different ways though.
Reply
#5
(Aug-12-2022, 07:04 PM)woooee Wrote: Pass gui.currentUserProcess 1 or 2 to the process as an arg. Each process can then update it.

I tried it. This is the code I got, in case I did something wrong:
class Gui(object):
    def __init__(self, q):
        self.root = Tk()
        self.root.geometry('150x100')

        self.frameP1 = LabelFrame(self.root, text="Process1", font=("Helvetica", 14, "bold"), bd=0)
        self.frameP1.pack(padx=12)
        self.currentUserProcess1 = Label(self.frameP1, text="Current User p1", font=("Helvetica", 10, "bold"))
        self.currentUserProcess1.pack()
        
        self.frameP2 = LabelFrame(self.root, text="Process2", font=("Helvetica", 14, "bold"), bd=0)
        self.frameP2.pack()
        self.currentUserProcess2 = Label(self.frameP2, text="Current User p2", font=("Helvetica", 10, "bold"))
        self.currentUserProcess2.pack()

def process1():
    print("Executing process1")
    
    #doSomething

def process2(currentUserProcess2):
    print("Executing process2")
    log = "Current user process 2"
    currentUserProcess2.configure(text=log)

def startProcesses():
    global p1
    global p2
    p1 = mp.Process(target = process1, args=(gui.currentUserProcess2,))
    p2 = mp.Process(target = process2, args=(gui.currentUserProcess2,))
    p1.start()
    p2.start()


def stopProcesses():
    p1.terminate()
    p2.terminate()
       
if __name__ == '__main__':
    q = mp.Queue()
    gui = Gui(q)
    p1 = mp.Process(target = process1, args=(gui.currentUserProcess2,))
    p2 = mp.Process(target = process2, args=(gui.currentUserProcess2,))
    p1.start()
    p2.start()
    gui.root.mainloop()
I got this:

Error:
Traceback (most recent call last): File "c:\Users\User1\Desktop\MultiTkinter\main.py", line 63, in <module> p1.start() File "C:\Users\User1\AppData\Local\Programs\Python\Python310\lib\multiprocessing\process.py", line 121, in start self._popen = self._Popen(self) File "C:\Users\User1\AppData\Local\Programs\Python\Python310\lib\multiprocessing\context.py", line 224, in _Popen return _default_context.get_context().Process._Popen(process_obj) File "C:\Users\User1\AppData\Local\Programs\Python\Python310\lib\multiprocessing\context.py", line 327, in _Popen return Popen(process_obj) File "C:\Users\User1\AppData\Local\Programs\Python\Python310\lib\multiprocessing\popen_spawn_win32.py", line 93, in __init__ reduction.dump(process_obj, to_child) File "C:\Users\User1\AppData\Local\Programs\Python\Python310\lib\multiprocessing\reduction.py", line 60, in dump ForkingPickler(file, protocol).dump(obj) TypeError: cannot pickle '_tkinter.tkapp' object PS C:\Users\User1\Desktop\MultiTkinter> Traceback (most recent call last): File "<string>", line 1, in <module> File "C:\Users\User1\AppData\Local\Programs\Python\Python310\lib\multiprocessing\spawn.py", line 107, in spawn_main new_handle = reduction.duplicate(pipe_handle, File "C:\Users\User1\AppData\Local\Programs\Python\Python310\lib\multiprocessing\reduction.py", line 79, in duplicate return _winapi.DuplicateHandle( PermissionError: [WinError 5] Access is denied
I deleted CheckQueuePoll function as I understand it wouldn't be needed if I'm passing "gui.CurrenUserProcess2" in the parameters.
Reply
#6
I see at least 2 problems
        self.currentUserProcess1 = Label(self.frameP1, text="Current User p1", font=("Helvetica", 10, "bold"))
        self.currentUserProcess2 = Label(self.frameP2, text="Current User p2", font=("Helvetica", 10, "bold"))
 
p1 = mp.Process(target = process1, args=(gui.currentUserProcess2,))
p2 = mp.Process(target = process2, args=(gui.currentUserProcess2,))
                                                                                                        ===
def process1():
Reply
#7
Are you trying to do something like this?

import multiprocessing as mp
import random as rnd
import tkinter as tk

'''
    Function for updating labels
    Creates the que
    Add to the que
    Set label text for que
    Call root.after for continuous call
'''
def get_num(root, label):
    myque = mp.Queue()
    myque.put(rnd.randint(1, 100))
    label['text'] = f'Process {myque.get()} running...'
    root.after(1000, lambda: get_num(root, label))

'''
    Tkinter window
'''
root = tk.Tk()
root.title('Running Processes')
root.columnconfigure(0, weight=1)
root.geometry('+300+300')

'''
    Two list, one to hold labelframes and one to hold labels
'''
labels = []
labelframes = []

'''
    Set variable j to for labelframe numbers
'''
j = 1

'''
    Using for loop to add 10 labels
    using j to number labelframes
    create and append labelframes to the labelframes list
'''
for i in range(10):
    j = j if i % 2 == 0 else(j if i % 3 == 0 else j+1)
    labelframes.append(tk.LabelFrame(root, text=f'Processes for frame {j}'))
    labelframes[i].grid(column=0, row=i, sticky='new', pady=5, padx=5)

    '''
    parent is used to place labels in the labelframes. Using i % n in this example
    '''
    parent = labelframes[0] if i % 2 == 0 else(labelframes[1] if i % 3 == 0 else labelframes[i])

    '''
    Create and append labels to the labels list
    Using parent to color background of grouped labels in labelframe
    '''
    labels.append(tk.Label(parent, anchor='w', padx=5, width=50))
    labels[i]['bg'] = 'sandybrown' if parent == labelframes[0] \
    else('tan' if parent == labelframes[1] else 'ivory2')
    labels[i]['relief'] = 'ridge'
    labels[i].grid(column=0, row=i, sticky='new', pady=5, padx=5)

    '''
    Create and start the process
    '''
    process = mp.Process(target=get_num, args=(root, labels[i],))
    process.start()
    process.join()

    '''
    Use root.after to call the get_num function
    '''
    root.after(1, get_num, root, labels[i])
root.mainloop()
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Tkinter: An image and label are not appearing. emont 7 646 Mar-21-2024, 03:00 PM
Last Post: deanhystad
  tkinter destroy label inside labelFrame Nick_tkinter 3 4,562 Sep-17-2023, 03:38 PM
Last Post: munirashraf9821
  [Tkinter] Updating tkinter text BliepMonster 5 6,061 Nov-28-2022, 01:42 AM
Last Post: deanhystad
  [Tkinter] The Text in the Label widget Tkinter cuts off the Long text in the view malmustafa 4 4,930 Jun-26-2022, 06:26 PM
Last Post: menator01
  [Tkinter] Making entry global in tkinter with multiprocessing luckyingermany 2 2,341 Jan-21-2022, 03:46 PM
Last Post: deanhystad
  tkinter: Image to Label Maryan 10 5,302 Oct-29-2020, 01:48 PM
Last Post: joe_momma
  Tkinter - How can I extend a label widget? TurboC 2 2,801 Oct-13-2020, 12:15 PM
Last Post: zazas321
  Tkinter: How to assign calculated value to a Label LoneStar 7 3,876 Sep-03-2020, 08:19 PM
Last Post: LoneStar
  [Tkinter] updating tkinter chart from within function mikisDW 1 1,935 Jul-02-2020, 03:33 AM
Last Post: deanhystad
  changing tkinter label from thread nanok66 3 7,374 Jun-07-2020, 01:37 AM
Last Post: nanok66

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020