Summary: I am experiencing the issue TypeError: cannot pickle '_tkinter.tkapp' object
I believe this is fixable by
How do I do that with my code - new to multiprocessing.
This is a sample of the Code I am working with:
import customtkinter
import tkinter
import multiprocessing
import time
def SampleProcess(self,x):
MY_STATUS = None
slaved = False
# Iterate through frames
for row in range(4):
for col in range(3):
if not(slaved):
name = f"frame{row}{col}"
# Find frame that hasn't been initialized
if getattr(self,'status_for_' + name).get() == f"Waiting for Input for {name}":
# claim frame
MY_STATUS = getattr(self,'status_for_' + name)
slaved = True
if slaved:
# rename text of frame
MY_STATUS.set("I have a Window!")
self.update_idletasks()
self.update()
class App(customtkinter.CTk):
'''GUI APP'''
# NAME DEFAULT WIDTH AND HEIGHT
APP_NAME = "Simulation Manager"
WIDTH = 1000
HEIGHT = 500
def __init__(self, *args, **kwargs):
customtkinter.set_appearance_mode("dark")
customtkinter.set_default_color_theme("dark-blue")
super().__init__(*args, **kwargs)
# Set Size info
self.title(App.APP_NAME)
self.geometry(f"{App.WIDTH}x{App.HEIGHT}")
self.minsize(App.WIDTH, App.HEIGHT)
# ============ create CTkFrames ============
# 4 x 3 grid
self.grid_columnconfigure(0, weight=1)
self.grid_columnconfigure(1, weight=1)
self.grid_columnconfigure(2,weight=1)
self.grid_rowconfigure(0, weight=1)
self.grid_rowconfigure(1, weight=1)
self.grid_rowconfigure(2, weight=1)
self.grid_rowconfigure(3, weight=1)
self.grid_rowconfigure(4, weight=0)
# make all frames
for row in range(4):
for col in range(3):
name = f"frame{row}{col}"
setattr(self, name, customtkinter.CTkFrame(master=self, corner_radius=10))
getattr(self,name).grid(row=row, column=col, padx=5, pady=5, sticky="nsew")
setattr(self,'status_for_' + name,tkinter.StringVar(value=f"Waiting for Input for {name}"))
setattr(self,'label_for_' + name, customtkinter.CTkLabel(master=getattr(self,name),
textvariable=getattr(self, 'status_for_' + name),
text_font=("Roboto Medium", -12)))
getattr(self,'label_for_' + name).grid(row=10, column=0, pady=(0,0), padx=0)
# Add Button
self.bottom_frame = customtkinter.CTkFrame(master=self, corner_radius=10)
self.bottom_frame.grid(row=4, column=1, padx=5, pady=5, sticky="nsew")
self.button = customtkinter.CTkButton(master=self.bottom_frame,
text="Begin Running",
command=self.start_sims,
width=120, height=30,
border_width=0,
corner_radius=8)
self.button.grid(pady=10, padx=20)
# closing func
def on_closing(self, event=0):
self.destroy()
def start(self):
self.mainloop()
# Button press Function
def start_sims(self):
pool = multiprocessing.Pool()
processes = [pool.apply_async(SampleProcess, (self,x,)) for x in range(10)]
result = [p.get() for p in processes]
# Run Client
if __name__ == "__main__":
app = App()
app.start()
What the code is intended to do, is to set up 12 "Frames" for each process running. Then launch each of the processes. Within each process it will assign itself to a specific frame, then "SampleProcess" should update the String Var of that frame to thus change the GUI display, and give new information on the status of the subprocess.
The sample code given works, and outputs the intended error.
How should I restructure the code to account for the pickling issue, by running the GUI separately. Again, the only interaction needed between TKinter and the multiprocesses is to send strings over to update the frames to give the programs current status.