如何通过在其中一个进程中找到的 'if' 验证在使用多处理操作的程序中一个接一个地关闭所有进程?

How to close all the processes one by one in a program that operates with multiprocessing by means of an 'if' validation found in one of them process?

import multiprocessing
from threading import Thread
import speech_recognition as sr

def actions_func(conn1_3,conn2_3):

def capture_cam(conn1, conn1b):

def audio_listening(conn2, conn2b):
    global catch_current_frame
    catch_current_frame = False

    # start dameon thread to handle frame requests:
    Thread(target=handle_catch_current_frame_requests, args=(conn2,), daemon=True).start()
    Thread(target=handle_cam_activate_requests, args=(conn2b,), daemon=True).start()

    while True:
        r = sr.Recognizer()

        with sr.Microphone() as source:
            catch_current_frame = False
            r.adjust_for_ambient_noise(source)
            print("Please say something...")
            audio = r.listen(source)

            try:
                text = r.recognize_google(audio, language="es-ES")
                print("You have said: \n " + repr(text))

                #Verifications
                if text.lower() == "capture":
                    catch_current_frame = True
                elif text.lower() == "Close your program":
                    #This is where I need to close processes p1, p2 and p3
                    break
                else:
                    pass

            except Exception as e:
                print("Error : " + str(e))


def main_process(finish_state):
    conn1, conn1_3 = multiprocessing.Pipe(duplex=True)
    conn2, conn2_3 = multiprocessing.Pipe(duplex=True)
    conn1b, conn2b = multiprocessing.Pipe(duplex=True)

    #Process 1
    p1 = multiprocessing.Process(target=capture_cam, args=(conn1, conn1b, ))
    p1.start()
    #Process 2
    p2 = multiprocessing.Process(target=audio_listening, args=(conn2, conn2b, ))
    p2.start()
    #Process 3
    p3 = multiprocessing.Process(target=actions_func, args=(conn1_3 ,conn2_3 ,))
    p3.start()

if __name__ == '__main__':
    finish_state = multiprocessing.Event()
    main_process(finish_state)

print("continue the code... ")

我需要当变量 text 等于 "Close your program" 时关闭 3 个活动进程(p1p2p3)。

我试过这样做:

elif text.lower() == "Close your program":
    print("the process has been interrupted!")
    finish_state.set()
    for process in [p1, p2, p3]:
        process.terminate()

但它对我不起作用,如果 text 等于 "Close your program",我需要一个更好的代码,允许我在该代码块中一个一个地关闭它们。

在这种情况下,我应该怎么做才能将所有进程都一一关闭?

可以尝试以下Event-based解决方案(但还有更简单的解决方案可供遵循):

main_process 传递给 audio_listening 一个额外的参数,finish_state:

def main_process():
    conn1, conn1_3 = multiprocessing.Pipe(duplex=True)
    conn2, conn2_3 = multiprocessing.Pipe(duplex=True)
    conn1b, conn2b = multiprocessing.Pipe(duplex=True)

    #Process 1
    p1 = multiprocessing.Process(target=capture_cam, args=(conn1, conn1b, ))
    p1.start()
    #Process 2
    finish_state = multiprocessing.Event()
    p2 = multiprocessing.Process(target=audio_listening, args=(conn2, conn2b, finish_state))
    p2.start()
    #Process 3
    p3 = multiprocessing.Process(target=actions_func, args=(conn1_3 ,conn2_3 ,))
    p3.start()

    finish_state.wait()
    p1.terminate()
    p2.terminate() # Not really necessary since the process is ending by itself
    p3.terminate()

if __name__ == '__main__':
    main_process()

请注意,现在 main_process 正在创建 finish_state multiprocessing.Event 实例;似乎没有必要将其作为参数传递。设置事件后,主进程将终止它创建的子进程。

然后在audio_processing:

def audio_listening(conn2, conn2b, finish_state):
    ...
                if text.lower() == "capture":
                    catch_current_frame = True
                elif text.lower() == "Close your program":
                    # Set the finish state event:
                    finish_state.set()
                    break

甚至还有两个甚至不需要 Event 变量的更简单的替代方案:

audio_process 进程处于无限循环中,直到它收到“关闭您的程序”消息或收到异常。在这两种情况下,它都会终止,然后我们可能希望其他两个进程也终止。因此,主进程可以在启动所有其他进程后调用 p2.join() 以等待 audio_process 进程完成,然后:

  1. 调用 p1.terminate(),然后调用 p3.terminate()
  2. 或者启动进程 p1p3 指定 daemon=True,例如p1 = multiprocessing.Process(target=capture_cam, args=(conn1, conn1b), daemon=True)。作为守护进程,它们现在将在主进程终止后立即自动终止。因此,不需要在这些进程上调用 terminate