[英]How to gracefully end asyncio program with CTRL-C when using loop run_in_executor
The following code requires 3 presses of CTRL-C to end, how can I make it end with one only?下面的代码需要按 3 次 CTRL-C 才能结束,我怎样才能让它只按一次结束呢? (So it works nicely in Docker)
(因此它在 Docker 中运行良好)
import asyncio
import time
def sleep_blocking():
print("Sleep blocking")
time.sleep(1000)
async def main():
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, sleep_blocking)
try:
asyncio.run(main())
except KeyboardInterrupt:
print("Nicely shutting down ...")
I've read many asyncio related questions and answers but can't figure this one out yet.我已经阅读了许多与 asyncio 相关的问题和答案,但还无法弄清楚这一点。 The 1st CTRL-C does nothing, the 2nd prints "Nicely shutting down..." and then hangs.
第一个 CTRL-C 什么都不做,第二个打印“Nicely shutting down...”然后挂起。 The 3rd CTRL-C prints an ugly error.
第三次 CTRL-C 打印出一个丑陋的错误。
I'm on Python 3.9.10 and Linux.我在 Python 3.9.10 和 Linux 上。
(edit: updated code per comment @mkrieger1) (编辑:根据@mkrieger1 的评论更新代码)
The way to exit immediately and unconditionally from a Python program is by calling os._exit().立即无条件退出 Python 程序的方法是调用 os._exit()。 If your background threads are in the middle of doing something important this may not be wise.
如果你的后台线程正在做一些重要的事情,这可能是不明智的。 However the following program does what you asked (python 3.10, Windows10):
但是,以下程序会按照您的要求进行操作(python 3.10,Windows10):
import asyncio
import time
import os
def sleep_blocking():
print("Sleep blocking")
time.sleep(1000)
async def main():
loop = asyncio.get_event_loop()
loop.run_until_complete(loop.run_in_executor(None, sleep_blocking))
try:
asyncio.run(main())
except KeyboardInterrupt:
print("Nicely shutting down ...")
os._exit(42)
From here we know that it's effectively impossible to kill a task running in a thread executor.从这里我们知道实际上不可能终止在线程执行器中运行的任务。 If I replace the default thread executor with a
ProcessPoolExecutor
, I get the behavior you're looking for.如果我用
ProcessPoolExecutor
替换默认线程执行器,我会得到您正在寻找的行为。 Here's the code:这是代码:
import concurrent.futures
import asyncio
import time
def sleep_blocking():
print("Sleep blocking")
time.sleep(1000)
async def main():
loop = asyncio.get_event_loop()
x = concurrent.futures.ProcessPoolExecutor()
await loop.run_in_executor(x, sleep_blocking)
try:
asyncio.run(main())
except KeyboardInterrupt:
print("Nicely shutting down ...")
And the result is:结果是:
$ python asynctest.py
Sleep blocking
^CNicely shutting down ...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.