当我的程序收到KeyboardInterrupt时,我想调用一段代码(self.client.logout()
),它会提示我的循环中运行的任务正常退出。
这是我的基本循环:
loop = asyncio.get_event_loop()
loop.run_until_complete(self.client.start(token))
我最初尝试简单地处理KeyboardInterrupt
:
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(self.client.start(token))
except KeyboardInterrupt:
loop.run_until_complete(self.client.logout())
finally:
loop.close()
但是在按Ctrl + C和self.client.logout()
被调用之间存在很大的延迟(变量,≈1分钟)。
通过为SIGINT
/ SIGTERM
添加处理程序,我设法在Unix系统上获得了我想要的效果:
import signal
loop = asyncio.get_event_loop()
# enable the bot to respond to SIGINT/SIGTERM (Unix only)
try:
loop.add_signal_handler(signal.SIGINT, lambda: asyncio.ensure_future(self.client.logout())
loop.add_signal_handler(signal.SIGTERM, lambda: asyncio.ensure_future(self.client.logout())
except NotImplementedError:
pass # program is running in Windows - nothing we can do
try:
loop.run_until_complete(self.client.start(token))
except KeyboardInterrupt:
loop.run_until_complete(self.client.logout())
finally:
loop.close()
当我按Ctrl + C或停止运行程序的systemd守护程序时,会立即调用注销函数。
我可以做些什么来在Windows上实现同样的目标?
答案 0 :(得分:0)
但是,您可能有很多阻塞或高 cpu 函数在没有空间用于 KeyboardInterrupt 的情况下运行。 Asyncio 确实在 Windows 和 KeyboardInterrupts 方面存在问题,因此事件循环有时会挂起,但使用 self.client.run_until_complete(self.client.start(token))
应该可以减轻或消除这些问题,至少以我的经验来看。但是对 loop.run_forever()
的调用总是有很小的机会错过中断并使程序挂起。