首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python异步程序不会退出

Python异步程序不会退出
EN

Stack Overflow用户
提问于 2016-09-06 14:50:28
回答 1查看 10.1K关注 0票数 13

我有一个包含两个异步任务的异步/Python程序:

  • 撞车者
  • 一种永远存在的。

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

代码语言:javascript
复制
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()

它打印错误,但不退出。当手动关闭时,程序将打印以下堆栈跟踪:

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-13 16:34:38

当异常在任务中上升时,它永远不会通过事件循环(即loop.run_until_complete(tasks)调用)传播到任务启动的作用域。想想看,好像异常只在任务的上下文中抛出,而这是您有机会处理它的顶级范围,否则它将在“背景”中上升。

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

代码语言:javascript
复制
try:
    loop.run_until_complete(tasks)
except (Exception, KeyboardInterrupt) as e:
    print('ERROR', str(e))
    exit()

...and --这正是事件循环的工作方式。想象一下,如果您有一个包含多个任务的服务,其中一个任务会失败,那么整个服务就会停止。

当您在停止播放中捕获异常时,您可以做的是手动执行事件循环。

代码语言:javascript
复制
async def task_1():
    await asyncio.sleep(1)
    try:
        assert False
    except Exception:
        # get the eventloop reference somehow
        eventloop.stop()

然而,这是非常肮脏的,有点麻烦,所以我建议采用@D建议的解决方案,因为它更干净、更安全。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39351988

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档