Python asyncio 程序不会退出

标签 python python-asyncio

我有一个带有两个异步任务的 asyncio/Python 程序:

  • 崩溃的
  • 一个永远持续下去的人。

我希望我的整个程序在第一次崩溃后退出。我无法让它发生。

import asyncio
import time

def infinite_while():
    while True:
        time.sleep(1)


async def task_1():
    await asyncio.sleep(1)
    assert False


async def task_2():
    loop = asyncio.get_event_loop()
    await loop.run_in_executor(None, lambda: infinite_while())


loop = asyncio.get_event_loop()
asyncio.set_event_loop(loop)

tasks = asyncio.gather(task_2(), task_1())
try:
    loop.run_until_complete(tasks)
except (Exception, KeyboardInterrupt) as e:
    print('ERROR', str(e))
    exit()

它打印 ERROR 但不退出。手动关闭时,程序会打印以下堆栈跟踪:

Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/lib/python3.5/concurrent/futures/thread.py", line 39, in _python_exit
    t.join()
  File "/usr/lib/python3.5/threading.py", line 1054, in join
    self._wait_for_tstate_lock()
  File "/usr/lib/python3.5/threading.py", line 1070, in _wait_for_tstate_lock
    elif lock.acquire(block, timeout):
KeyboardInterrupt

最佳答案

当任务中出现异常时,它永远不会传播到通过事件循环启动任务的范围,即 loop.run_until_complete(tasks) 调用。想一想,好像异常仅在您的任务上下文中抛出,那是您有机会处理它的顶级范围,否则它将在“后台”.

这就是说,你永远不会从任务中捕获 Exception:

try:
    loop.run_until_complete(tasks)
except (Exception, KeyboardInterrupt) as e:
    print('ERROR', str(e))
    exit()

...这就是事件循环的工作原理。想象一下,如果您的服务有多个任务,其中一个任务失败,整个服务就会停止。

你可以做的是 stop当您在 task1 中捕获异常时手动执行事件循环,例如

async def task_1():
    await asyncio.sleep(1)
    try:
        assert False
    except Exception:
        # get the eventloop reference somehow
        eventloop.stop()

但是,这很脏而且有点老套,所以我宁愿建议使用 @D-Von suggested 的解决方案。 ,更清洁、更安全。

关于Python asyncio 程序不会退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39351988/

相关文章:

python - numpy 中的矢量化二维移动窗口,包括边缘

python - 等待方法中的异步超时解释

python - 如何使用asyncio模块并发调用nameko服务

python - 如何在不从多 :prob 的开头开始的情况下,从其最后一次迭代中提升现有 xgboost 模型

python - 具有不同参数的 QPushbutton 子类

python - 使用 Python 从 MySQL 检索整数以执行数学函数

python - 让discordbot 等待用户的众多回复之一?

python - 如何在给定两个协程的 python 中实现,一直运行一个直到另一个完成

python-3.x - Tornado + aioredis : why are my redis calls blocking?

python - 如何在sqlalchemy中创建子查询