【问题标题】:Is it possible to inherit multiprocessing.Process to communicate with the main process是否可以继承 multiprocessing.Process 与主进程通信
【发布时间】:2017-09-29 19:40:25
【问题描述】:

我正在尝试从 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。 我覆盖了“运行”方法,因此当它被执行时,目标的返回值被放入队列中。 我有一个使用 Mprocess 类在主函数中调用的“getReturn”方法。仅当“Mprocess.isalive()”方法(为 multiprocessing.Process 定义)返回 false 时才应调用此方法。 但是这种机制不起作用,因为当我调用“Mprocess.start()”时,它会创建一个在自己的环境中运行目标的子进程。 我想知道有没有办法在start方法中使用队列来获取返回值,避免目标有队列参数进行通信。 我想概括这个模块。 我不希望我的方法被定义为有一个队列来获取返回值。 我想要一个模块,以便它可以适用于任何功能,因为我计划有一个管理器方法,它需要一个 dict["process_name/ID" : methods/targets],一个 dict["process name/ID " : [argument_list]] 并为每个目标创建一个进程并返回一个 dict["process_name/ID" : (return tuple, )。 任何想法都会受到欢迎。

编辑 经理职能:

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

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

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

我不想将队列传递给函数,然后返回队列。 我想制作一个通用模块,以便任何现有方法都可以使用多处理而不更改其定义,因此保持与其他模块的接口。 我不希望一个函数被设计成只作为一个进程运行,我希望有一个通用的接口,以便其他模块也可以使用这个函数作为一个正常的方法,而不必费心从队列中读取来获取返回价值。

【问题讨论】:

    标签: python python-multiprocessing


    【解决方案1】:

    评论:...这样我就可以从 start 方法开始的进程中获取返回值了

    这对我有用,例如:

    类处理器

    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

    【讨论】:

    • 如果我不将返回值放入队列中,那么拥有全局并将其祈祷给我的进程将不会这样做,这涉及更改目标函数的实现以使用该全局队列.
    • 嗨,我在 Mprocess 类中声明的队列对主程序可见,直到我拥有 Mprocess 对象,拥有一个全局队列并不能回答我的问题。因为当我执行 Mprocess.start() 时,start 方法会打开一个单独的进程,该进程拥有自己的进程内存并在其中运行目标。我想要的是一种重载start方法的方法,这样我就可以从start方法开始的进程中获取返回值,我已经尝试了你建议的方法,它不能解决我遇到的问题。
    • 而且使用“return_dict[process_wait.name] = global_Queue.get()”,代码可能会使用不是来自 process_wait.name 进程的 global_Queue.get() 值,因为我不知道其他进程完成的顺序,以及放入队列的返回值的顺序,这就是为什么我想要一个与每个进程关联的单独队列,所以我可以通过 Mprocess 对象本身访问它们。
    • 嗨,发送队列作为参数并将返回值放入队列中,这是我试图避免的。函数/目标应该使用“return”命令正常返回。我需要捕获该返回值。
    • @Pavan:也有可能,改变我的答案。
    猜你喜欢
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-06
    • 1970-01-01
    • 2020-06-16
    • 1970-01-01
    相关资源
    最近更新 更多