I am developing a program that does a polling and I need the polling to be done in a separate process for performance reasons. The program is pretty long, but I managed to reduce it to a minimum so it easier to understand. It is a two states machine, one idle and the other prints values that the separate process has put in a queue.
So the problem is that when order the multiprocessing process to Start, everything freezes. Only the process is running like crazy and the program does not react.
self.queue = Queue() #initialize a Queue
self.slave_process = Process(
target=self.write,
args =(self.queue,)) #Define our queue filler process
# Here is when it freezes
self.slave_process.start() #Ask the process to start
Please look at the code commentaries for further explanation.
Would you help me out with this?
import time
import threading
import tkinter as tk
from datetime import datetime
from multiprocess import Process
from multiprocessing import Queue
class Main(object):
# This is a very normal object initializer
# I will use a tkinter GUI to use a button
def __init__(self):
self.root = tk.Tk() #The root of tkinter
self.button1 = tk.Button(self.root,
text="Connect", command=self.btConnect,
padx=5, pady=5) #My button that executes btConnect()
self.button1.pack() #We pack the button
self.state = "idle" #Indicator of the initial state of the FSM
self.root.mainloop() #Instruction to make tkinter GUI run
# This state does pretty much nothing except print its name
# It should terminate when the self.state name changes
def stIdle(self):
while self.state == "idle":
print("stIdle")
# This state prints its name and,
# if there is a value in the queue it pops it and prints it
def stConnect(self):
while state == "connected":
print("stConnect")
if not self.queue.empty():
print(self.queue.get())
# This is the code the button executes
def btConnect(self):
print("acConnect") #First print something so we know it happened
if self.state == "idle": #if the state was idle
self.queue = Queue() #initialize a Queue
self.slave_process = Process(
target=self.write,
args =(self.queue,)) #Define our queue filler process
# Here is when it freezes
self.slave_process.start() #Ask the process to start
time.sleep(0.250) # Give the process some time to fill the queue
if not queue.empty(): # If is not empty then go to stConnect
self.state = "connected"
self.stConnect()
#threading.Thread(name="idle", target=self.stConnect).start()
# I would like to run stConnect in a thread, but for now OK
elif state == "connected":
# Idealistically I would like that hitting the button again
# would terminate the process, but for now is OK
self.state = "idle"
self.slave_process.terminate()
self.stIdle()
#threading.Thread(name="idle", target=self.stIdle).start()
def write(self, queue):
while True:
print("write")
queue.put("QUEUE")
Main()
I edited the code, changed the process.run() to process.start() and now it tells me this error as well as opening a new tkinter instance:
C:\Users\U4928\Documents\workspace\RawData>C:\Programs_RD\Python\Python36-32\python.exe test.py
acConnect
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Programs_RD\Python\Python36-32\lib\tkinter\__init__.py", line 1702, in __call__
return self.func(*args)
File "test.py", line 39, in btConnect
self.slave_process.start()
File "C:\Programs_RD\Python\Python36-32\lib\site-packages\multiprocess\process.py", line 112, in start
self._popen = self._Popen(self)
File "C:\Programs_RD\Python\Python36-32\lib\site-packages\multiprocess\context.py", line 223, in _Popen
return _default_context.get_context().Process._Popen(process_obj)
File "C:\Programs_RD\Python\Python36-32\lib\site-packages\multiprocess\context.py", line 322, in _Popen
return Popen(process_obj)
File "C:\Programs_RD\Python\Python36-32\lib\site-packages\multiprocess\popen_spawn_win32.py", line 65, in __init__
reduction.dump(process_obj, to_child)
File "C:\Programs_RD\Python\Python36-32\lib\site-packages\multiprocess\reduction.py", line 63, in dump
ForkingPickler(file, protocol).dump(obj)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 437, in dump
self.save(obj)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 549, in save
self.save_reduce(obj=obj, *rv)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 662, in save_reduce
save(state)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Programs_RD\Python\Python36-32\lib\site-packages\dill\_dill.py", line 893, in save_module_dict
StockPickler.save_dict(pickler, obj)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 856, in save_dict
self._batch_setitems(obj.items())
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 882, in _batch_setitems
save(v)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Programs_RD\Python\Python36-32\lib\site-packages\dill\_dill.py", line 1069, in save_instancemethod0
pickler.save_reduce(MethodType, (obj.__func__, obj.__self__), obj=obj)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 638, in save_reduce
save(args)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 771, in save_tuple
save(element)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 549, in save
self.save_reduce(obj=obj, *rv)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 662, in save_reduce
save(state)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Programs_RD\Python\Python36-32\lib\site-packages\dill\_dill.py", line 893, in save_module_dict
StockPickler.save_dict(pickler, obj)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 856, in save_dict
self._batch_setitems(obj.items())
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 882, in _batch_setitems
save(v)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 549, in save
self.save_reduce(obj=obj, *rv)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 662, in save_reduce
save(state)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Programs_RD\Python\Python36-32\lib\site-packages\dill\_dill.py", line 893, in save_module_dict
StockPickler.save_dict(pickler, obj)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 856, in save_dict
self._batch_setitems(obj.items())
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 882, in _batch_setitems
save(v)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Programs_RD\Python\Python36-32\lib\site-packages\dill\_dill.py", line 893, in save_module_dict
StockPickler.save_dict(pickler, obj)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 856, in save_dict
self._batch_setitems(obj.items())
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 887, in _batch_setitems
save(v)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 549, in save
self.save_reduce(obj=obj, *rv)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 662, in save_reduce
save(state)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 504, in save
f(self, obj) # Call unbound method with explicit self
File "C:\Programs_RD\Python\Python36-32\lib\site-packages\dill\_dill.py", line 893, in save_module_dict
StockPickler.save_dict(pickler, obj)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 856, in save_dict
self._batch_setitems(obj.items())
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 882, in _batch_setitems
save(v)
File "C:\Programs_RD\Python\Python36-32\lib\pickle.py", line 524, in save
rv = reduce(self.proto)
TypeError: can't pickle _tkinter.tkapp objects
A process is started by calling start() on it, which will setup the process run method to run in a separate process.
So try replacing: self.slave_process.run() with self.slave_process.start()
It's explained here :https://docs.python.org/3/library/multiprocessing.html?highlight=process#multiprocessing.Process
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With