【问题标题】:asyncio create_task() to be first in queue?asyncio create_task() 在队列中排在第一位?
【发布时间】:2019-07-27 17:08:16
【问题描述】:

据我所知,当我调用 create_task() 时,它会放在事件循环队列的末尾。

我的用例如下,我有一些由同一个协程组成的任务。我想在某些失败的情况下取消所有任务。这是模式:

async def coro(params):
   # long running task...
   if failed_condition:
        await cancel_all()  # should cancel all tasks made of coro

async def cancel_all():
   for task in tasks:
        task.cancel()
    await asyncio.gather(*tasks)  # wait for cancel completion
    print("All tasks cancelled")

tasks = []
async def main():

    tasks = [loop.create_task(coro(params)) for x in range(5)]
    asyncio.gather(*tasks)

问题在于,由于cancel_all()本身正在等待一个任务,所以它会被自己取消。

我该如何解决这个问题? 我可以改用 loop.create_task(cancel_all()),但我希望 cancel_all() 尽快运行。

【问题讨论】:

    标签: python python-asyncio


    【解决方案1】:

    cancel_all() 可以排除当前任务:

    async def cancel_all():
        to_cancel = set(tasks)
        to_cancel.discard(asyncio.current_task())
        for task in to_cancel:
            task.cancel()
        await asyncio.gather(*to_cancel)
    

    【讨论】:

      【解决方案2】:

      您可以将asyncio.waitFIRST_EXCEPTION 参数一起使用。

      import asyncio
      import random
      
      class UnexpectedCondition(Exception):
          pass
      
      async def coro(condition):
          # long running task...
          await asyncio.sleep(random.random()*10)
          if condition:
              raise UnexpectedCondition("Failed")
          return "Result"
      
      async def main(f):
          tasks = [coro(f(x)) for x in range(5)]
          done, pending = await asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION)
      
          for p in pending:
              # unfinished tasks will be cancelled
              print("Cancel")
              p.cancel()
      
          for d in done:
              try:
                  # get result from finished tasks
                  print(d.result())
              except UnexpectedCondition as e:
                  # handle tasks with unexpected conditions
                  print(e)
      
      asyncio.run(main(lambda x: x%2 == 0))
      

      【讨论】:

        猜你喜欢
        • 2021-12-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-03
        • 2019-04-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-11
        相关资源
        最近更新 更多