问题 asyncio - 如何在信号处理程序中使用协同程序?


我正在开发一个使用python3.4的asyncio进行网络连接的应用程序。当此应用程序干净地关闭时,节点需要与集线器“断开连接”。此断开连接是一个需要网络连接的活动进程,因此循环需要在关闭之前等待此操作完成。

我的问题是使用协程作为信号处理程序将导致应用程序不关闭。请考虑以下示例:

import asyncio
import functools
import os
import signal

@asyncio.coroutine
def ask_exit(signame):
    print("got signal %s: exit" % signame)
    yield from asyncio.sleep(10.0)
    loop.stop()

loop = asyncio.get_event_loop()
for signame in ('SIGINT', 'SIGTERM'):
    loop.add_signal_handler(getattr(signal, signame),
                                        functools.partial(ask_exit, signame))

print("Event loop running forever, press CTRL+c to interrupt.")
print("pid %s: send SIGINT or SIGTERM to exit." % os.getpid())
loop.run_forever()

如果您运行此示例然后按Ctrl + C,则不会发生任何事情。 问题是,如何使用siganls和coroutines来实现这种行为?


11123
2018-04-26 16:35


起源

我在python-tulip列表上找到了答案: groups.google.com/d/msg/python-tulip/Jce-VVXJZvk/o-g74rtuIHkJ - Jinnog
如果你认为你找到了解决方案(使用信号安排协程 asyncio.async 而不是直接将其称为信号处理程序);你可以 将其作为您自己的答案发布并接受 以便其他人可以看到问题得到解答。不相关:你可能会在网站上侮辱一些志愿者,建议他们帮助你的动机是虚构的互联网点。 - jfs


答案:


python> = 3.5的语法

loop = asyncio.get_event_loop()
for signame in ('SIGINT', 'SIGTERM'):
    loop.add_signal_handler(getattr(signal, signame),
                            lambda: asyncio.ensure_future(ask_exit(signame)))

7
2018-02-10 04:59





loop = asyncio.get_event_loop()
for signame in ('SIGINT', 'SIGTERM'):
    loop.add_signal_handler(getattr(signal, signame),
                            asyncio.async, ask_exit(signame))

这样,信号会导致您的ask_exit被安排在任务中。


4
2017-08-07 08:58



读者注意:这只是UNIX。可悲的是。 - ereOn
这是python 3.5.1中的无效语法。 - Jared Mackey
在Python 3.6.4中,ask_exit从未等待过异常 - jerrypy