Python 使用初始化程序子类化进程

Python subclassing process with initialiser

我正在尝试创建一个对象作为新进程。如果我给 class 一个初始化器,程序就会显示错误。

代码

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'

错误

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'

但是当向初始化器插入行 super(My_class, self).__init__() 时,程序 运行 没问题。

最终构造函数:

def __init__(self):
    super(My_class, self).__init__()
    self.name = "Hello "+self.name
    self.num = 20

我在不同的上下文中找到该行并在此处尝试,代码运行良好。

谁能解释一下上面初始化程序中 super(My_class, self).__init__() 行的作用是什么?

当您在此处添加自己的 __init__() 时,您将 覆盖 超类中的 __init__()。然而,超类通常(在本例中)在其 __init__() 中有一些它需要的东西。因此,您要么必须重新创建该功能(例如,按照错误中所述初始化 _popen 等),要么使用新构造函数 within 调用超类构造函数super(My_class, self).__init__()(或 Python 3 中的 super().__init__())。

嗯,您的 class 中没有 _popen。

如果 _popen 是在 class 级别声明的或者是 mp.Process 中的一个函数,那么您的代码 工作,因为它会从进程命名空间。

class Process(object):

    _popen = None

    def __init__(...):
       #stuff, but not involving _popen

然而断言看起来像一个守卫,我猜代码看起来有点像:

class Process(object):


    def __init__(...):
       #let's make sure that we don't open twice
       self._popen = None

现在,在这种情况下,_popen 仅在实例上设置,而不在进程上设置 class。但是为了设置它,您需要执行 mp.Process.__init__ 代码。

如果您调用 'Process.__init__',您的代码将完美运行,而您最初并没有这样做。

您可以使用

来调用它,而不是使用 Super
class My_Class(mp.Process):

   def __init__(self):
       #
       mp.Process.__init__(self)
       ....do your stuff....

我以前就是这样做的,效果很好。但是,如果您将继承更改为 My_Class(mp.AnotherProcessType),它就会中断。在这种情况下,任何对 mp.Process.somefunc() 的调用,而不仅仅是 __init__ 都需要手动调整。

super(My_Class, self).init() 在这种情况下最终会做同样的事情,但是为了调用 mp.Process.__init__.

有时您可以不对 Python class 的祖先调用 init。但这完全取决于是否有初始化代码需要运行。在这种情况下,它看起来像有。

此外,如果您的 class 中没有 __init__ 那么您也不必担心,mp.Process.__init__ 会被调用自动地。但是你自己的__init__的存在基本上就是说"I'll do my own initialization, thank you very much"。如有必要,由您的代码明确地将一些工作委托回祖先class。

p.s。不用担心,我发现 super(xxx,self).somefunc() 也有点非 Python 晦涩。但它有效。