Search code examples
pythonmultithreadingpython-multiprocessing

multiprocessing process gets started directly at creation


Hi I have a problem with multiprocessing in python 3.7 I've made a listener, that should be waiting for a response from a server without blocking the rest of the program (asynchronous communication):

self = cl.appendSend('bar', base_list)
print("client erstellt neuen nebenläufigen listener, für die Antwort des Servers")
multiprocessing.set_start_method("spawn")
queue = multiprocessing.Queue()
process = multiprocessing.Process(target = cl.appendResponse(), args=(self))
process.start()
print("listener aktiv")

thread = threading.Thread(target= waitingPrinter(), args=(process, queue))
print(thread)

is where everything is started but the line process = multiprocessing.Process(target = cl.appendResponse(), args=(self)) is started once, runs through and then after being done, it just runs again. The debugger never leaves this line.

The method run in the process is:

 def appendResponse(self):
        print("nebenläufiger listener aktiv")
        msgrcv = self.chan.receive_from(self.server)
        print("nebenläufiger listener hat Antwort erhalten")
        return msgrcv  # pass it to caller

Sadly becaus of copyright I can't really post more, but the method runs through fine the first time and fails the second with the message : Traceback (most recent call last):

> File "D:/Verteile Systeme 2/neues Lab/git/vs2lab/lab2/rpc/runcl.py",
> line 27, in <module>
>     process = multiprocessing.Process(target = cl.appendResponse(), args=(self))   File "C:\Program Files
> (x86)\Python37-32\lib\multiprocessing\process.py", line 82, in
> __init__
>     self._args = tuple(args) TypeError: 'Client' object is not iterable

So I am wondering, why is the process with cl.appendResponse() even started upon binding to the process and doesn't wait for process.start() and if not already in the answer to that, why does it then run directly a second time. And of course how can I fix that.

Also is there a way to replaces processing with thread and still get a return value? I am having a lot of trouble with processing and return values.


Solution

  • The cause of the the apparent immediate execution of the process has been correctly stated by philipp in their answer.
    The target argument to Process takes a callable object, that is to be invoked by the run() method. Your code passes whatever is returned by self.chan.receive_from(self.server).
    There is no subprocess running in or from the line process = multiprocessing.Process(target = cl.appendResponse(), args=(self)). Your method runs in the main process and blocks it.
    On a side note: you will have the exact same issue with your thread, for the same reason: thread = threading.Thread(target= waitingPrinter(), args=(process, queue))

    After your method has finished executing in the main process, the initialization of your process object raises the TypeError inside the __init__ method of the BaseProcess class.
    You pass an argument, self, to your process, but you do it incorrectly. The args argument requires a tuple of arguments. The creation of a tuple through a literal needs a trailing comma if only a single value is specified: args=(self,). Your code effectively passes self, i.e. a Client object directly, which is not iterable and thus causes the error.
    In your case, appendResponse appears to be a bound method of the Client object. It will receive the self argument through the inner workings of Python's class system. Passing it explicitly through the process will raise another TypeError for passing two positional arguments to a method that only takes one. Unless appendSend returns something else than the Client instance cl, that you call it on, drop the args parameter in the process instantiation.

    On another side note: the start method spawn is the only one available on Windows and thus the default. Unless your code needs to run under Unix using that start method, this line is redundant: multiprocessing.set_start_method("spawn")