asyncio:安排工作项目,安排其他工作项目

时间:2019-03-10 20:30:50

标签: python python-asyncio

我正在编写一个Python程序,该程序可以计划要发生的许多异步,受I / O约束的项目,其中许多也将计划其他类似的工作项目。这些工作项本身是完全相互独立的,它们不需要彼此的结果都完整,也不需要从它们那里收集任何结果以进行任何本地输出(除了日志记录之外,它是日志记录的一部分)工作项本身。

我最初使用的是这样的模式:

type step struct {
    i int
    j int
}
type steps []step

steps = append(steps, step{3, 4}, step{5, 6})

但是,我遇到了一些嵌套的async def some_task(foo): pending = [] for x in foo: # ... do some work ... if some_condition: pending.append(some_task(bar)) if pending: await asyncio.wait(pending) 调用有时会永远挂起的麻烦,尽管asyncio.wait(pending)的单个操作总是可以完成的(根据调试时产生的调试输出)我使用await列出了未收集结果的状态,该结果显示所有期货都处于KeyboardInterrupt状态。当我向其他人寻求帮助时,他们说我应该改用done,但我没有找到任何有关如何执行此操作的有用信息,也无法从提出此建议的人那里得到澄清。

那么,我怎么满足这个用例?

1 个答案:

答案 0 :(得分:3)

Python asyncio.Queue可能有助于将程序处理与程序完成联系起来。它具有join()方法,该方法将一直阻塞,直到队列中的所有项目都已收到并处理为止。

我喜欢的另一个好处是,工人从队列处理中拉出来时变得更加明确,可能添加了更多项目,然后添加了ACKS,但这只是个人喜好。

async def worker(q):
    while True:
      item = await queue.get()

      # process item potentially requeue more work
      if some_condition:
         await q.put('something new')

      queue.task_done()


async def run():
  queue = asyncio.Queue()
  worker = asyncio.ensure_future(worker(queue))
  await queue.join()
  worker.cancel()


loop = asyncio.get_event_loop()
loop.run_until_complete(run())
loop.close()

上面的示例改编自asyncio producer_consumer示例,并进行了修改,因为您的工作人员都消费和生产:

https://asyncio.readthedocs.io/en/latest/producer_consumer.html


我不太确定如何解决您的特定示例,但我想看看asyncio提供的原语来帮助事件循环挂接到程序状态,尤其是join并使用{{1} }。