何时使用loop.Add_Signal_Handler? [英] When to use loop.add_signal_handler?
问题描述
我注意到异步库有一个loop.add_signal_handler(signum, callback, *args)
方法。
到目前为止,我只是在主文件中使用signals
模块捕获Unix信号,我的异步代码如下所示:
signal.signal(signal.SIGHUP, callback)
async def main():
...
这是我的疏忽吗?
推荐答案
add_signal_handler
documentation是稀疏的1,但是查看the source,似乎与signal.signal
相比的主要附加值是,add_signal_handler
将确保信号唤醒事件循环,并允许循环调用信号处理程序以及其他排队的回调和可运行的协程。
到目前为止,我只是使用Signals模块在主文件中捕获Unix信号[.]这是我的疏忽吗?
这取决于信号处理程序正在做什么。打印一条消息或更新全局消息是可以的,但如果它引用了任何与Asyncio有关的内容,那很可能是疏忽。信号可以在(几乎)任何时候传递,包括在执行异步Callback、协程期间,甚至在Asyncio自己记账期间。
例如,asyncio.Queue
的自由实现假设对队列的访问是单线程的、不可重入的。使用q.put_nowait()
向队列添加内容的信号处理程序如果中断同一队列上正在进行的q.put_nowait()
调用,将是灾难性的。与多线程代码中遇到的典型争用情况类似,对_unfinished_tasks
赋值过程中的中断很可能导致它仅递增一次,而不是递增两次(每个put_nowait
递增一次)。
异步代码是designed用于协作多任务,其中功能可能挂起的点由await
和相关关键字明确表示。add_signal_handler
函数确保您的信号处理程序在这样的点上被调用,并且您可以像实现任何其他异步回调一样自由地实现它。
1最初编写此答案时,
add_signal_handler
文档比现在的briefer版本更低,完全没有涵盖与signal.signal
的区别。此问题提示它同时获得expanded。
这篇关于何时使用loop.Add_Signal_Handler?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!