Asyncio 子进程在中断时没有被正确取消

问题描述 投票:0回答:0

我有以下代码无法按我预期的方式工作。我希望能够使用 SIGINT (Ctrl-C) 中断我的程序。然后它应该取消运行子进程的任务并在取消时运行一些代码,但我无法运行该部分。似乎信号被我设置的事件处理程序以外的其他东西拦截了。这不是我所期望的。

在 python 3.10.63.11.2

上运行
import asyncio
import signal

jobs = set()

async def create_worker():
    task = asyncio.create_task(worker())
    jobs.add(task)
    task.add_done_callback(jobs.discard)

async def worker():
    try:
        proc = await asyncio.create_subprocess_shell(
            'sleep 10',
        )
        await proc.communicate()
        print("done")
    except asyncio.CancelledError:
        print("my task is getting cancelled :\\") # should run this section, but doesn't
        raise

async def main() -> None:
    loop = asyncio.get_event_loop()
    loop_hold = asyncio.Event()

    async def graceful_shutdown():
        if jobs:
            await asyncio.sleep(2.0) # doesn't run, the jobs were stopped earlier

        unfinished_jobs = list(jobs)

        if unfinished_jobs:
            for job in unfinished_jobs:
                job.cancel()

            await asyncio.wait(unfinished_jobs)

        loop_hold.set()

    loop.add_signal_handler(
        signal.SIGINT,
        lambda: asyncio.create_task(graceful_shutdown())
    )

    for _ in range(10):
        await create_worker()
    
    await loop_hold.wait()

if __name__ == "__main__":
    asyncio.run(main())

当我在命令完成之前使用 Ctrl-C 中断程序时,我期望在取消工人时运行一些代码。也许像下面这样:

my task is getting cancelled :\
my task is getting cancelled :\
...
my task is getting cancelled :\

但我得到的是这个:

done
done
...
done

我也用

asyncio.create_subprocess_exec
试过这个,但我遇到了同样的问题。

python python-3.x subprocess python-asyncio
© www.soinside.com 2019 - 2024. All rights reserved.