I'm trying to create a object as a new process. If I give an initialiser to the class, program is showing an error.
Code
import multiprocessing as mp
import time
class My_class(mp.Process):
def __init__(self):
self.name = "Hello "+self.name
self.num = 20
def run(self):
print self.name, "created and waiting for", str(self.num), "seconds"
time.sleep(self.num)
print self.name, "exiting"
if __name__ == '__main__':
print 'main started'
p1=My_class()
p2=My_class()
p1.start()
p2.start()
print 'main exited'
Error
File "/usr/lib64/python2.7/multiprocessing/process.py", line 120, in start
assert self._popen is None, 'cannot start a process twice'
AttributeError: 'My_class' object has no attribute '_popen'
But when a insert the line super(My_class, self).__init__()
to the initialiser, the program is running fine.
Final constructor:
def __init__(self):
super(My_class, self).__init__()
self.name = "Hello "+self.name
self.num = 20
I found that line in a different context and tried here and the code is working fine.
Can anybody please explain what is the work of the line super(My_class, self).__init__()
in the above initialiser?
When you add your own __init__()
here, you are overriding the __init__()
in the superclass. However, the superclass often (as in this case) has some stuff it needs in its __init__()
. Therefore, you either have to re-create that functionality (e.g. initializing _popen
as described in your error, among other things), or call the superclass constructor within your new constructor using super(My_class, self).__init__()
(or super().__init__()
in Python 3).
Well, you don't have a _popen in your class.
If _popen was declared at the class level or was a function in mp.Process, then your code would work because it would grab it off the Process namespace.
class Process(object):
_popen = None
def __init__(...):
#stuff, but not involving _popen
The assert looks like a guard however and I'll guess that the code looks somewhat like:
class Process(object):
def __init__(...):
#let's make sure that we don't open twice
self._popen = None
Now, in this case, _popen is only set on the instance, not on the Process class. But in order for it to be set, you need to execute that mp.Process.__init__ code.
Your code would work perfectly well, if you called 'Process.__init__', which you didn't originally do.
Instead of using Super, you could call it instead with
class My_Class(mp.Process):
def __init__(self):
#
mp.Process.__init__(self)
....do your stuff....
this is what I used to do and it works fine. But it breaks if you change the inheritance to say My_Class(mp.AnotherProcessType). In that case, any calls to mp.Process.somefunc(), not just __init__ would need to be adjusted manually.
super(My_Class, self).init() ends up doing the same exact thing in this case but is a more robust way to do the housework in order to call mp.Process.__init__.
You can sometimes away with not calling an init on a the ancestor of a Python class. But it all depends on whether there is initialization code that needs running. And in this case, it looks like there is.
Also if you didn't have an __init__ in your class then you also wouldn't have to worry, mp.Process.__init__ would have been called automatically. But the existence of your own __init__ basically says "I'll do my own initialization, thank you very much". It's up to your code to explicitly delegate some work back to the ancestor class if necessary.
p.s. not to worry, I find super(xxx,self).somefunc() a bit un-pythonically obscure as well. But it works.
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