首页 > 解决方案 > 如何避免父母在python多处理中等待孩子?

问题描述

我对 python 多处理相当陌生,我正在尝试编写一个能够异步执行函数和附加回调的类。

首先,让我们为这个特定问题解决一个通用命名法:

┬─ process1 (parent)
└─┬─ process2 (child of parent1)
  └─── process3 (child of parent2)

在记录了我关于这个主题的一些内容并遵循这个 SO question之后,为了做到这一点,我为该run方法提出了以下代码:

import multiprocessing


class AsyncProcess:
    def __init__(self, target, callback=None, args=(), kwargs={}):
        self._target = target
        self._callback = callback
        self._args = args
        self._kwargs = kwargs
        self._process = None

    def run(self):
        def wrapper():
            return_value = self._target(*self._args, **self._kwargs)

            if self._callback is not None:
                process = multiprocessing.Process(target=self._callback, args=(return_value,))
                process.start()
                multiprocessing.process._children.discard(process)

        self._process = multiprocessing.Process(target=wrapper)
        self._process.start()

该类AsyncProcess比这更大(它旨在作为适配器在新进程multiprocessing.Processsubprocess.Popen执行外部进程和 python 函数);这就是为什么它不是它的子类,multiprocessing.Process而只是使用它(以防有人想知道)。

我在这里想要实现的是能够process3从另一个进程(process2)中启动一个子进程(),而无需process2等待子进程(process3)(因为孩子可能需要更长的时间才能完成比父母)。的daemon属性multiprocessing.Process没有用,因为当父进程死亡(process2)时,子进程(process3)也被杀死(我只想让它运行直到它完成)。

但是,我提出的解决方案有两点我完全不喜欢:

  1. 我正在修补 的内部结构multiprocessing,我有点不喜欢。
  2. 由于我正在process3从父 ( ) 的子池中删除子进程 ( process2),我猜这会留下可怜的孤儿(我真的不知道究竟意味着什么,但最肯定的是根本没有好的做法)。

这里的问题是如何实现父母不等待孩子而不实际杀死孩子或陷入孤儿进程?有没有其他更正确或更优雅的方式来实现我想要做的事情?

我正在考虑将子进程( )分配给process3产生这个子进程()的进程的父进程process1,即子进程的祖父进程(我知道它肯定会活着),但我还没有找到方法真正做到这一点。


一些澄清

  1. Popen做我想要实现的,但它只用外部进程来做,即我不能通过使用Popen(我当然知道)执行一个包含所有上下文的python函数。
  2. os.fork想到了使用,但我发现区分父代码和子代码的方法有点麻烦(处理PID == 0PID != 0案例等)。
  3. 我没有考虑过使用该threading包的任何解决方案,因为我想管理进程,而不是线程,并将线程管理留给操作系统。
  4. 从直接process3开始process1解决孤儿进程的问题,但是我必须进行主动轮询process1才能知道何时process2完成,这实际上不是一个选项(process1管理无法阻止的服务器)。
  5. 我需要process2尽快完成以便从中获取一些数据;这就是为什么我不process3直接执行 inside的内容process2

我在写这个问题时想出了一些东西

由于我的问题是必须process3从内部process2启动并从中启动它可以process1解决问题,但主动轮询process1不是一种选择,我也可以同时从内部启动process2process3process1对象传递process2给并process3执行主动轮询process3间隔,以确保process2完成后的快速响应。

这是否有任何意义,或者对于已经解决的问题(而且我不知道)它是一个过于复杂的解决方案?

标签: pythonmultiprocessingpython-multiprocessing

解决方案


您想要做的事情(忽略它是否是一个好主意的问题)对于多处理库来说是不可能的,而不需要对您想要避免的内部进行修补,这正是因为多处理库是专门为子进程设计的不要比父母长寿。

我认为答案确实是使用subprocess.Popen(),尽管这意味着要放弃多处理库的高级 API。不,你不能直接执行 Python 函数,但你可以创建一个单独的 script.py 来调用你想要的函数。


推荐阅读