我想使用多处理来同时运行一系列冗长操作的多个进程(例如,使用计算机视觉同时单击程序)。我想在 GUI 中实现一个停止按钮,这样我就可以中途停止进程 - 但我不确定如何做这样的事情。
我知道如果存在循环,我可以使用关闭事件来控制进程 - 但在我的情况下,目标函数不是循环。这是一些代码,我基本上只是对目标函数的每一行进行了事件检查:
(我删除了大部分 tkinter 代码,因为它不相关,启动/停止功能适用于 GUI 中各自的按钮。)
from multiprocessing import Event, Process
from time import sleep
def start_proc(self):
self.proc_stop_event.clear()
for i in range(4):
p = Process(target=long_sequential_tasks, args=(i,self.proc_stop_event))
p.start()
def stop_proc(self):
self.proc_stop_event.set()
#a series of lengthy, different and sequential tasks
def long_sequential_tasks(idx, event):
if not event.is_set(): <---
print(str(idx))
sleep(10)
else:
break
if not event.is_set(): <---
print(str(idx * 2))
sleep(10)
else:
break
if not event.is_set(): <---
print(str(idx * 3))
sleep(10)
else:
break
检查每一行的事件状态显然不是一个解决方案,但我真的不知道我还能做什么。将来我想添加队列和锁来同步并行进程,显然 process.terminate 可以让它们挂起。
因此,如果 process.terminate 不是一个选项,我怎样才能以干净的方式中断正在执行一系列操作的进程?或者我仍然可以终止进程但清理挂起的东西?
最佳答案
Q : how can I interrupt a process that's carrying out a sequence of actions in a clean way?
可以使用 nanomsg 或 ZeroMQ 实现信令/消息传递元平面,它将智能地通知进程(它正在检查是否存在这样的 <NO-GO>
-消息,作为在阶段之间的适当位置的示例)纯-[SERIAL]工作流程检查点)
一次<NO-GO>
-消息到达时,进程可以执行优雅的清理并智能终止其自身的运行。
附加成本极低。
def long_sequential_tasks( idx ):
#-----------------------------------------------------------------------
# local
# mock-up soft-authentcation proxy
# for otherwise possible ( whitelisting & key-management & other tools available )
#
CONTROL_HASH_ID = "asdfhasrtbnastnve9vaergn9ervgnaeragiagiab - WHATEVER"
LENofMASK = len( CONTROL_HASH_ID )
#-----------------------------------------------------------------------
import zmq
aCtx = zmq.Context()
aSUB = aCtx.socket( zmq.SUB )
aSUB.setsockopt( zmq.SUBSCRIBE, CONTROL_HASH_ID )
aSUB.setsockopt( zmq.LINGER, 0 )
...
aSUB.connect( "<protocol>://<address-details>" ) # { ipc:// | tipc:// | norm:// | tcp:// | vmci:// | ... }
if ( 0 == aSUB.poll( 0, zmq.POLLIN )
or aSUB.recv( zmq.NOBLOCK )[:LENofMASK] != CONTROL_HASH_ID
): # <--- NO LEGAL EXPLICIT <NO-GO>-MESSAGE HERE
# continue planned work-step
...
if ( 0 == aSUB.poll( 0, zmq.POLLIN )
or aSUB.recv( zmq.NOBLOCK )[:LENofMASK] != CONTROL_HASH_ID
): # <--- NO LEGAL EXPLICIT <NO-GO>-MESSAGE HERE
# continue planned work-step
...
以干净的方式实现了所要求的效果。
基于 Tkinter MVC actor 的 GUI 和任何其他智能控制消息“源”都可以接受这个概念,并在 tk.mainloop()
的世界之外启动智能信号/消息传递。 -调度程序并轻松实现跨平台集成计算外系统(十多年来一直使用该系统作为远程 GUI,用于具有 AI/ML + 交易后端生态系统的 QuantFX 原型(prototype)设计)。
另一种方法是通过使用自定义信号处理程序来实现退出计划。这就不再需要构建以相当严格的方式检查退出计划之后/之前的步骤序列。信号处理程序可以“中断”计算流,并且可能(相当残酷地)终止自己的进程(如果必须优雅终止,则需要添加一些缓解措施),但如果值得长期运行工作流程步骤,则代表一种选择停止在一些外部逻辑上,负责退出计划标记 <NO-GO>
-状态。
关于Python多处理: How to shutdown a long running process that is a sequence of actions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57979411/