You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Asyncio Quart问题:任务已销毁但仍处于待处理状态

解决Quart + Asyncio的"Task was destroyed but it is pending!"异常

问题详情

遇到Asyncio与Quart结合时的异常,错误核心提示:

Task was destroyed but it is pending!
task: <Task pending name='Task-1672902' coro=<ASGIHTTPConnection.handle_messages() running at /usr/local/lib/python3.8/site-packages/quart/asgi.py:56> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7feb66ff0190>()]>

异常指向Quart的ASGIHTTPConnection.handle_messages()函数,当前环境:

  • Python版本:3.8.12
  • Quart版本:0.19.3
    无法稳定复现该问题,缺少更多上下文追踪信息。

可能的原因

  • 客户端提前断开连接:用户在请求处理过程中主动关闭浏览器或客户端连接,导致Quart负责处理该连接的异步任务还处于pending状态就被销毁
  • 后台任务管理不当:应用中存在未被正确await或未在 shutdown 阶段处理的后台任务,进程退出时被强制销毁
  • 版本兼容性bug:Quart 0.19.3与Python 3.8的异步任务调度机制存在已知兼容问题,后续版本已修复部分ASGI连接处理逻辑

可行的解决方案

  1. 升级Quart到最新稳定版
    Quart 0.19.x属于较旧版本,后续发布的版本(如0.20.x及以上)修复了大量异步任务管理和ASGI相关的bug,执行命令升级:

    pip install --upgrade quart
    
  2. 优雅处理连接断开异常
    在请求处理的业务代码中捕获asyncio.CancelledError,确保任务能正常收尾,示例:

    from quart import Quart
    import asyncio
    
    app = Quart(__name__)
    
    @app.route("/")
    async def index():
        try:
            # 你的业务逻辑
            await asyncio.sleep(5)
            return "OK"
        except asyncio.CancelledError:
            # 连接断开时的收尾操作,比如释放资源
            print("Connection cancelled, cleaning up")
            raise
    
  3. 规范后台任务管理
    如果使用自定义后台任务,需确保任务能被正确跟踪和处理:

    • 使用asyncio.create_task()创建任务后,保存任务引用
    • 在应用 shutdown 时(通过@app.before_serving或@app.after_serving钩子)主动取消任务并等待其结束:
      background_tasks = set()
      
      @app.route("/start-task")
      async def start_task():
          task = asyncio.create_task(long_running_task())
          background_tasks.add(task)
          task.add_done_callback(background_tasks.discard)
          return "Task started"
      
      async def long_running_task():
          try:
              await asyncio.sleep(30)
          except asyncio.CancelledError:
              pass
      
      @app.before_serving
      async def setup():
          app.background_tasks = set()
      
      @app.after_serving
      async def cleanup():
          for task in app.background_tasks:
              task.cancel()
              try:
                  await task
              except asyncio.CancelledError:
                  pass
      
  4. 增加日志排查
    添加异步任务的生命周期日志,方便后续复现时追踪任务上下文:

    import logging
    import asyncio
    
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger(__name__)
    
    def log_task(task):
        try:
            result = task.result()
            logger.info(f"Task {task.get_name()} completed with result: {result}")
        except asyncio.CancelledError:
            logger.info(f"Task {task.get_name()} was cancelled")
        except Exception as e:
            logger.error(f"Task {task.get_name()} failed: {e}", exc_info=True)
    
    # 创建任务时添加日志回调
    task = asyncio.create_task(handle_messages())
    task.add_done_callback(log_task)
    

内容的提问来源于stack exchange,提问作者Saad elkheety

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 03:28:28