python - 如何避免父母在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.Process
中subprocess.Popen
执行外部进程和 python 函数);这就是为什么它不是它的子类,multiprocessing.Process
而只是使用它(以防有人想知道)。
我在这里想要实现的是能够process3
从另一个进程(process2
)中启动一个子进程(),而无需process2
等待子进程(process3
)(因为孩子可能需要更长的时间才能完成比父母)。的daemon
属性multiprocessing.Process
没有用,因为当父进程死亡(process2
)时,子进程(process3
)也被杀死(我只想让它运行直到它完成)。
但是,我提出的解决方案有两点我完全不喜欢:
- 我正在修补 的内部结构
multiprocessing
,我有点不喜欢。 - 由于我正在
process3
从父 ( ) 的子池中删除子进程 (process2
),我猜这会留下可怜的孤儿(我真的不知道究竟意味着什么,但最肯定的是根本没有好的做法)。
这里的问题是如何实现父母不等待孩子而不实际杀死孩子或陷入孤儿进程?有没有其他更正确或更优雅的方式来实现我想要做的事情?
我正在考虑将子进程( )分配给process3
产生这个子进程()的进程的父进程process1
,即子进程的祖父进程(我知道它肯定会活着),但我还没有找到方法真正做到这一点。
一些澄清:
Popen
做我想要实现的,但它只用外部进程来做,即我不能通过使用Popen
(我当然知道)执行一个包含所有上下文的python函数。os.fork
想到了使用,但我发现区分父代码和子代码的方法有点麻烦(处理PID == 0
和PID != 0
案例等)。- 我没有考虑过使用该
threading
包的任何解决方案,因为我想管理进程,而不是线程,并将线程管理留给操作系统。 - 从直接
process3
开始process1
解决孤儿进程的问题,但是我必须进行主动轮询process1
才能知道何时process2
完成,这实际上不是一个选项(process1
管理无法阻止的服务器)。 - 我需要
process2
尽快完成以便从中获取一些数据;这就是为什么我不process3
直接执行 inside的内容process2
。
我在写这个问题时想出了一些东西:
由于我的问题是必须process3
从内部process2
启动并从中启动它可以process1
解决问题,但主动轮询process1
不是一种选择,我也可以同时从内部启动process2
,process3
将process1
对象传递process2
给并process3
执行主动轮询process3
间隔,以确保process2
完成后的快速响应。
这是否有任何意义,或者对于已经解决的问题(而且我不知道)它是一个过于复杂的解决方案?
解决方案
您想要做的事情(忽略它是否是一个好主意的问题)对于多处理库来说是不可能的,而不需要对您想要避免的内部进行修补,这正是因为多处理库是专门为子进程设计的不要比父母长寿。
我认为答案确实是使用subprocess.Popen()
,尽管这意味着要放弃多处理库的高级 API。不,你不能直接执行 Python 函数,但你可以创建一个单独的 script.py 来调用你想要的函数。
推荐阅读
- microsoft-graph-api - 对于具有 URL 编码文件名的项目,如何通过路径获取 Sharepoint/OneDrive 驱动器项目
- java - ORACLE WLS 基础设施安装错误
- python - 从具有开始和结束日期的数据框列生成日期范围
- angular - 使用角度 10 中的纬度和经度从当前位置获取用户地址
- r - R - 创建假人来评估星期几的效果
- reactjs - 当我尝试使用 AuthProvider 和 useAuth 时出现白色空白屏幕(react + firebase)
- reporting-services - 是否可以选择在第一页隐藏页眉并根据 ssrs 报告中的页码显示剩余页面
- gitlab - GITLAB:将脚本输出保存在变量 .gitlab-ci.yml 中
- r - 如何设置 4 位日期?
- r - xy.coords(x, y) 中的逻辑回归错误:“x”和“y”长度不同