簡體   English   中英

使用循環 run_in_executor 時如何使用 CTRL-C 優雅地結束異步程序

[英]How to gracefully end asyncio program with CTRL-C when using loop run_in_executor

下面的代碼需要按 3 次 CTRL-C 才能結束,我怎樣才能讓它只按一次結束呢? (因此它在 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 ...")

我已經閱讀了許多與 asyncio 相關的問題和答案,但還無法弄清楚這一點。 第一個 CTRL-C 什么都不做,第二個打印“Nicely shutting down...”然后掛起。 第三次 CTRL-C 打印出一個丑陋的錯誤。

我在 Python 3.9.10 和 Linux 上。

(編輯:根據@mkrieger1 的評論更新代碼)

立即無條件退出 Python 程序的方法是調用 os._exit()。 如果你的后台線程正在做一些重要的事情,這可能是不明智的。 但是,以下程序會按照您的要求進行操作(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)

這里我們知道實際上不可能終止在線程執行器中運行的任務。 如果我用ProcessPoolExecutor替換默認線程執行器,我會得到您正在尋找的行為。 這是代碼:

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 ...")

結果是:

$ python asynctest.py
Sleep blocking
^CNicely shutting down ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM