0

How can I start a multiprocessing.Process from within __init__() of a class, targeting another function in that class? The class itself shall not be a process. __init__() shall refer to a class variable assigned in the class, not inside any function.

Working code:

import multiprocessing as mp
class SomeClass:
    def __init__(self):
        p_process1 = mp.Process(target=self.process1)
        p_process1.start()

    def process1(self):
        while True:
            pass

The code I want:

import multiprocessing as mp
class SomeClass:
    def __init__(self):
        self.p_process1.start()

    def process1(self):
        while True:
            pass
    p_process1 = mp.Process(target=process1)

If I now try to run the code I want, I get an error message:

Process Process-1:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/multiprocessing/process.py", line 249, in _bootstrap
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/multiprocessing/process.py", line 93, in run
    self._target(*self._args, **self._kwargs)
TypeError: process1() missing 1 required positional argument: 'self'

2 Answers2

2

Well the problem clearly states it: the multiprocessing calls it without parameters, and you however expect one: self. In this case you can solve it like:

import multiprocessing as mp

class SomeClass:
    def __init__(self):
        self.p_process1.start()

    @staticmethod
    def process1(): # so no parameter
        while True:
            pass
    p_process1 = mp.Process(target=process1)

If however you need a reference to self, there is no other option than to construct the method in a context where you have a reference to self. After all if you fetch self.process1, you do not get a reference to SomeClass.process1, you obtain a function that is equal to functools.partial(SomeClass.process1,self=self), so you actually have a function where self is filled in implicitly.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
1

process1 is a bound function, it needs class instance as self to be the first arg when be called.

If you just want that arch, @property can help.

import multiprocessing as mp
class SomeClass:
    def __init__(self):
        self.p_process1.start()

    def process1(self):
        while True:
            pass

    @property
    def p_process1(self):
        return mp.Process(target=self.process1)

SomeClass()
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
Valens
  • 164
  • 3
  • If I do so, I'll be able to use `SomeClass().process1()`, but not `SomeClass.process1()`, or won't I be able to use any of them? Will process1 only be callable from `__init__()`? – Andreas is moving to Codidact Mar 07 '17 at 15:59
  • Also, will this always run `__init__()`? – Andreas is moving to Codidact Mar 07 '17 at 18:17
  • Is SomeClass a Object-oriented class and you want to use its instance? If not and you want to call SomeClass.process1(), you must make it as a staticmethod as @Willem Van Onsem said. And you even don't need __init__. – Valens Mar 08 '17 at 13:38
  • No. From another class, I start SomeClass, `SomeClass()`. This'll start two processes. Main class: Host, Graphics Class = SomeClass. In the main class, the script is run in a while loop. Called by `Host().startup`. "process1()" is a model of "displayer()" and "handler()". I have problems with threads crashing, or getting a pygame fatal error, segmentation fault. I'm going to create a new question for this, as I don't know how to fix this. Perhaps I can send you the link? – Andreas is moving to Codidact Mar 09 '17 at 08:30
  • You can provide the link in comment – Valens Mar 09 '17 at 14:33
  • Sorry, but do you know about somewhere else to post the question instead? I've got a warning for these kind of questions. I don't want to become unable to post more. – Andreas is moving to Codidact Mar 09 '17 at 14:43