Python 父进程使用asynio.add\u signal\u处理程序捕获子进程的终止信号

Python 父进程使用asynio.add\u signal\u处理程序捕获子进程的终止信号,python,multiprocessing,signals,python-asyncio,Python,Multiprocessing,Signals,Python Asyncio,我有一个asyncio事件循环,我使用loop.add\u signal\u handler()向其中添加了一个信号处理程序。我想要捕捉的信号是SIGINT、SIGHUP和SIGTERM,以优雅地关闭我的事件循环 从这个事件循环中,我想使用multiprocessing.Process()来分叉进程。此过程p我希望能够使用p.terminate()从事件循环终止。但是,信号处理程序将捕获由p.terminate()发出的SIGTERM信号,提示执行我的关机代码,使p保持运行 我还没有找到任何解决

我有一个asyncio事件循环,我使用
loop.add\u signal\u handler()
向其中添加了一个信号处理程序。我想要捕捉的信号是SIGINT、SIGHUP和SIGTERM,以优雅地关闭我的事件循环

从这个事件循环中,我想使用
multiprocessing.Process()
来分叉进程。此过程
p
我希望能够使用
p.terminate()
从事件循环终止。但是,信号处理程序将捕获由
p.terminate()
发出的SIGTERM信号,提示执行我的关机代码,使
p
保持运行

我还没有找到任何解决办法。大多数帖子说,你应该避免使用终止信号,通过传递例如
None
来尝试使用
multiprocessing.Queue()
,并在子进程中处理。虽然我看到了这种方法的有用性和简洁性,但在我的例子中,使用
多处理.Queue()
将是不可行的。我是在尝试不可能的事情还是错过了什么

我创建了一个最低限度的示例:

import asyncio
import multiprocessing as mp
import signal
import time


class Test():

    def __init__(self):
        self.event_loop = asyncio.get_event_loop()

    def create_mp(self):
        # Wrapper for creating process
        self.p = mp.Process(target=worker)
        self.p.start()
    
    async def shutdown_mp(self):
        # Shutdown after 5 sec
        await asyncio.sleep(5)
        self.p.terminate()

    async def async_print(self):
        # Simple coroutine printing
        while True:
            await asyncio.sleep(1)
            print("Async_test")

    async def shutdown_event_loop(self, signal):
        # Graceful shutdown, inspiration from roguelynn (Lynn Root) 
        print("Received exit signal {}".format(signal.name))
        tasks = [t for t in asyncio.all_tasks() if t is not asyncio.current_task()]
        # Cancel all tasks
        [task.cancel() for task in tasks]
        print("Cancelling {} outstanding tasks".format(len(tasks)))
        await asyncio.gather(*tasks, return_exceptions=True)
        self.event_loop.stop()

    def run(self):
        # Add signals
        signals = (signal.SIGINT, signal.SIGHUP, signal.SIGTERM)
        for s in signals:
            self.event_loop.add_signal_handler(
                s, lambda s=s: self.event_loop.create_task(self.shutdown_event_loop(s)))
        # Schedule async task
        self.event_loop.create_task(self.async_print())
        # Start processes
        self.create_mp()
        # Schedule process to be terminated
        self.event_loop.create_task(self.shutdown_mp())
        self.event_loop.run_forever()

def worker():
    # Simple process
    while True:
        print("Test")
        time.sleep(1)

if __name__ == "__main__":
    test = Test()
    test.run()

我无法简单地
键盘中断
取消进程。相反,我使用
pgrep python3
kill-9pid

这不起作用,因为事件循环用于与其信号处理程序通信的内部管道最终在父级和子级之间共享,导致父级收到子级中实际发生的信号的通知<默认情况下,code>mp.Processfork,并且不支持在
fork()之后重用事件循环。看,也许有帮助。