Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiprocessing in Python blocks when asked to run

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
like image 553
Samson Gasparyan Avatar asked Apr 14 '26 10:04

Samson Gasparyan


1 Answers

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

like image 132
sdlarsen Avatar answered Apr 16 '26 23:04

sdlarsen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!