我对python多处理相当陌生,我正在尝试编写一个能够异步执行函数和附加回调的类。
首先,让我们为这个特定问题解决一个通用的命名法:
┬─ process1 (parent)
└─┬─ process2 (child of parent1)
└─── process3 (child of parent2)
在对我进行了一些关于这个主题的记录,并遵循这个SO问题之后,为了做到这一点,我为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.Process
和subprocess.Popen
之间的适配器,用于在新进程中执行外部进程和python函数(;这就是为什么它不是multiprocessing.Process
的子类,而只是使用它(以防有人想知道(。
我在这里要实现的是能够从另一个进程(process2
(中启动子进程(process3
(,而不必等待子进程(process2
process3
((因为子进程可能需要比父进程更长的时间(。multiprocessing.Process
的daemon
属性没有用,因为当父进程死亡 (process2
( 时,子进程 (process3
( 也被杀死(我只想让它运行直到它完成(。
但是,对于我想出的解决方案,有两件事我完全不喜欢:
- 我正在修补
multiprocessing
的内部结构,我有点不喜欢。 - 由于我正在从父级(
process2
(的子池中删除子进程(process3
(,我猜这会让可怜的孩子成为孤儿(我真的不知道这到底意味着什么,但肯定根本不是好的做法(。
这里的问题是,我怎样才能实现父母不等待孩子而不真正杀死孩子或陷入孤儿过程?有没有其他更正确或更优雅的方式来实现我想要做的事情?
我正在考虑将子进程(process3
(分配给产生此子进程(process1
(的进程的父进程,即子进程的祖父进程(我知道它肯定会活着(,但我还没有找到实际这样做的方法。
一些澄清:
Popen
做到了我想要实现的目标,但它只通过外部进程来实现,即我无法使用Popen
(当然,我知道(执行具有所有上下文的 python 函数。- 我想到了使用
os.fork
,但我发现区分父代码和子代码的方法有点麻烦(处理PID == 0
和PID != 0
情况等(。 - 我没有考虑过使用
threading
包的任何解决方案,因为我想管理进程而不是线程,并将线程管理留给操作系统。 - 从
process1
开始process3
直接解决了孤立进程的问题,但是然后我必须对process1
进行主动轮询才能知道process2
何时完成,这实际上不是一个选项(process1
管理无法阻止的服务器(。 - 我需要尽快完成
process2
以便从中获取一些数据;这就是为什么我不直接在process2
中执行process3
的内容。
我在写问题时想到的东西:
由于我的问题必须从process2
内部启动process3
并从process1
启动它可以解决问题,但对process1
进行主动轮询不是一种选择,所以我也可以同时从process1
内部启动process2
和process3
,将process2
对象传递给process3
并以较小的间隔对process3
执行主动轮询,以确保CC_后的快速响应43 完成。
这是否有任何意义,或者对于已经解决(我不知道(的事情来说,这是一个过于复杂的解决方案?
如果没有您想要避免的内部结构的修补,就不可能使用多处理库来执行您想要做的事情(忽略它是否是一个好主意的问题(,正是因为多处理库是专门为不会比父进程寿命更长的子进程设计的。
我认为答案确实是使用subprocess.Popen()
,尽管这意味着放弃多处理库的漂亮高级 API。不可以,您不能直接执行 Python 函数,但您可以创建一个单独的 script.py 来调用所需的函数。