【发布时间】:2017-04-15 07:28:11
【问题描述】:
我正在使用 Python 3.4.2 学习 asyncio,并使用它在 IPC 总线上持续监听,而 gbulb 在 DBus 上监听。
我创建了一个函数listen_to_ipc_channel_layer,它持续监听IPC通道上的传入消息并将消息传递给message_handler。
我也在听 SIGTERM 和 SIGINT。当我向运行您在底部找到的代码的 python 进程发送 SIGTERM 时,脚本应该正常终止。
我遇到的问题是以下警告:
got signal 15: exit
Task was destroyed but it is pending!
task: <Task pending coro=<listen_to_ipc_channel_layer() running at /opt/mainloop-test.py:23> wait_for=<Future cancelled>>
Process finished with exit code 0
…使用以下代码:
import asyncio
import gbulb
import signal
import asgi_ipc as asgi
def main():
asyncio.async(listen_to_ipc_channel_layer())
loop = asyncio.get_event_loop()
for sig in (signal.SIGINT, signal.SIGTERM):
loop.add_signal_handler(sig, ask_exit)
# Start listening on the Linux IPC bus for incoming messages
loop.run_forever()
loop.close()
@asyncio.coroutine
def listen_to_ipc_channel_layer():
"""Listens to the Linux IPC bus for messages"""
while True:
message_handler(message=channel_layer.receive(["my_channel"]))
try:
yield from asyncio.sleep(0.1)
except asyncio.CancelledError:
break
def ask_exit():
loop = asyncio.get_event_loop()
for task in asyncio.Task.all_tasks():
task.cancel()
loop.stop()
if __name__ == "__main__":
gbulb.install()
# Connect to the IPC bus
channel_layer = asgi.IPCChannelLayer(prefix="my_channel")
main()
我仍然对 asyncio 了解得很少,但我想我知道发生了什么。在等待 yield from asyncio.sleep(0.1) 时,信号处理程序捕获了 SIGTERM 并在该过程中调用 task.cancel()。
这不应该在while True: 循环中触发CancelledError 吗? (因为它不是,但这就是我的理解"Calling cancel() will throw a CancelledError to the wrapped coroutine")。
最终调用loop.stop() 停止循环,而无需等待yield from asyncio.sleep(0.1) 返回结果甚至整个协程listen_to_ipc_channel_layer。
如果我错了,请纠正我。
我认为我唯一需要做的就是让我的程序等待yield from asyncio.sleep(0.1) 返回结果和/或协程以中断while循环并完成。
我相信我混淆了很多事情。请帮我把这些事情弄清楚,这样我就可以弄清楚如何在没有警告的情况下优雅地关闭事件循环。
【问题讨论】:
标签: python python-3.x python-3.4 python-asyncio