asyncio之接收Unix信号
通常Unix系统事件通知需要中断应用来触发执行。当使用asyncio时,信号处理回调会与事件循环管理的其他协程的回调交错进行。这导致中断的功能更少,因此需要提供安全防护来清理不完整的操作。
信号处理必须是常规的函数调用,不是协程。
1 2 3 4 5 6 7 8 9
| import asyncio import functools import os import signal def signal_handler(name): print('signal_handler({!r})'.format(name))
|
使用add_signal_handler()注册信号处理。第一个参数是信号,第二个参数是回调。回调函数是没有参数的,所以如果函数需要参数可以使用functools.partial()。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| event_loop = asyncio.get_event_loop() event_loop.add_signal_handler( signal.SIGHUP, functools.partial(signal_handler, name="SIGHUP"), ) event_loop.add_signal_handler( signal.SIGUSR1, functools.partial(signal_handler, name='SIGUSR1'), ) event_loop.add_signal_handler( signal.SIGINT, functools.partial(signal_handler, name='SIGINT'), )
|
这个示例使用协程通过os.kill()发送信号给它自己。信号发送之后,协程让出控制来让处理程序运行。在一般的应用中,有更多的地方是应用代码返还给事件循环而不是像这样人为的返还。
1 2 3 4 5 6 7 8 9 10 11 12 13
| async def send_signals(): pid = os.getpid() print('starting send_signals for {}'.format(pid)) for name in ['SIGHUP', 'SIGHUP', 'SIGUSR1', 'SIGINT']: print('sending {}'.format(name)) os.kill(pid, getattr(signal, name)) print('yielding control') await asyncio.sleep(0.01) return
|
主程序运行send_signals()直到所有的信号发送完。
1 2 3 4
| try: event_loop.run_until_complete(send_signals()) finally: event_loop.close()
|
输出显示当发送信号之后send_signals()让出控制权,处理函数被调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| $ python3 asyncio_signal.py starting send_signals for 21772 sending SIGHUP yielding control signal_handler('SIGHUP') sending SIGHUP yielding control signal_handler('SIGHUP') sending SIGUSR1 yielding control yield_handler('SIGUSR1') sending SIGINT yielding control signal_handler('SIGINT')
|
signal - Receive notification of asynchronous system events
原文链接