是否可以继承multiprocessing.Process以与主进程

时间:2017-05-02 10:08:37

标签: python python-multiprocessing

我正在尝试从multiprocessing.Process继承一个子类,它将为每个瞬间提供一个队列,以便队列可用于捕获目标的返回值。 但问题是multiprocessing.Process.start()使用subprocess.Popen(https://github.com/python/cpython/blob/master/Lib/multiprocessing/process.py)创建进程并在其中运行目标。有没有办法在不定义/重载整个Process模块​​的情况下重载它。

这就是我要做的事情:

class Mprocessor(multiprocessing.Process):
    def __init__(self, **kwargs):
        multiprocessing.Process.__init__(self, **kwargs)
        self._ret = Queue.Queue()

    def run(self):
        self._ret.put(multiprocessing.Process.run(self))

    def getReturn(self):
        if self._ret.empty:
            return None
        return self._ret.get()

这里我尝试在类中创建一个multiprocessig.Queue。 我重写'run'方法,所以当它被执行时,目标的返回值被放入队列中。 我有一个'getReturn'方法,它使用Mprocess类在main函数中调用。只有在'Mprocess.isalive()'方法(为multiprocessing.Process定义)返回false时才应调用此方法。 但是这种机制不起作用,因为当我调用'Mprocess.start()'时,它会创建一个子进程,在自己的环境中运行目标。 我想知道是否有一种方法可以在start方法中使用队列来获取返回值,并避免目标有一个队列参数进行通信。 我想概括一下这个模块。 我不希望我的方法被定义为有一个队列来获取返回值。 我想要一个模块,以便它可以适用于任何函数,因为我计划有一个管理器方法,它接受一个dict [“process_name / ID”:methods / targets],一个dict [“进程名称/ ID “:[argument_list]]并为每个目标创建一个进程并返回一个dict [”process_name / ID“:(返回元组))。 任何想法都会受到欢迎。

修改 经理职能:

def Processor_call(func = None, func_args = None):
    if sorted(func.keys()) != sorted(func_args()):
        print "Names in func dict and args dict doesn't match"
        return None

    process_list = multiprocessing.Queue()
    for i in func.keys():
        p = Mprocessor(name = i, target = func[i], args = tuple(func_args[i]))  
        process_list.put(p)
        p.start()

    return_dict = {}
    while not process_list.empty():
        process_wait = process_list.get()
        if not process_wait.is_alive():
            process_wait.join()
            if process_wait.exitcode == 0:
                return_dict[process_wait.name] = process_wait.getReturn()
            else:
               print "Error in process %s, status not availabe" %process_wait.name
        else:
            join_process.put(process_wait)
    return return_dict

编辑:目标函数应该如下所示。

def sum(a , b):
    return a + b

我不想将队列传递给函数,并返回队列。 我想创建一个通用模块,以便任何现有方法都可以使用多处理而不需要对其定义进行任何更改,因此可以维护与其他模块的接口。 我不希望将一个函数设计为仅作为一个进程运行,我想拥有通用接口,以便其他模块也可以将此函数用作普通方法,而不必费心从队列中读取以获得返回值。

1 个答案:

答案 0 :(得分:1)

  

评论:...以便我从start方法开始的流程中获取返回值

这对我有用,例如:

  

类Mprocessor

class Mprocessor(multiprocessing.Process):
    def __init__(self, queue, **kwargs):
        multiprocessing.Process.__init__(self, **kwargs)
        self._ret = queue

    def run(self):
        return_value = self._target( *self._args )
        self._ret.put((self.name, return_value))
        time.sleep(0.25)
        exit(0)
  

启动流程并等待返回值

def Processor_call(func=None, func_args=None):
    print('func=%s, func_args=%s' % (func, func_args))

    ret_q = multiprocessing.Manager().Queue()
    process_list = []
    for i in func.keys():
        p = Mprocessor(name=i, target=func[i], args=(func_args[i],), queue=ret_q)
        p.start()
        process_list.append(p)
        time.sleep(0.1)

    print('Block __main__ until all process terminated')
    for p in process_list:
        p.join()

    print('Aggregate alle return values')
    return_dict = {}
    while not ret_q.empty():
        p_name, value = ret_q.get()
        return_dict[p_name] = value

    return return_dict
  

__ main __

if __name__ == '__main__':
    rd = Processor_call({'f1':f1, 'f2':f1}, {'f1':1, 'f2':2})
    print('rd=%s' % rd)
  

<强>输出
  func = {'f1':,'f2':},func_args = {'f1':1,'f2':2}
      pid:4501开始2
      pid:4501正在运行
      pid:4500开始1
      pid:4500运行
  阻止__main__直到所有进程终止为止       pid:4501正在运行
      pid:4500运行
      pid:4501正在运行
      pid:4500运行
  pid:4501终止
  pid:4500终止
  聚合等位基因返回值
  rd = {'f1':1,'f2':2}

使用Python测试:3.4.2和2.7.9

  

问题:是否可以继承multiprocessing.Process与主进程通信

是的,这是可能的。但使用class object,因为process使用了class object自己的副本。
您必须使用global Queue object并将其传递给process