简体   繁体   English

Python Asyncio如何从队列连续运行任务/协程

[英]Python Asyncio how to run Tasks/Coroutines Consecutively from a Queue

In another program I have made that utilises asyncio I am having to following problem: 在我制作的利用异步的另一个程序中,我不得不遇到以下问题:

in one function, two coroutines are awaited (on separate lines), however the first takes some time, before the first coroutine finishes, another function is called which awaits another coroutine, since this is awaited before the first finishes, the second coroutine of the first function has not been awaited yet, so the second function is run between the two coroutines of the first 在一个函数中,要等待两个协程(在单独的行上),但是第一个协程需要花费一些时间,在第一个协程完成之前,调用另一个函数来等待另一个协程,因为这是在第一个协程完成之前等待的,它是第二个协程尚未等待第一个函数,因此第二个函数在第一个的两个协程之间运行

My solution was to make some sort of global queue that coroutines would be added to so the run time wouldn't affect the order, I made a small test, but can't get it to work properly. 我的解决方案是制作一些将添加协程的全局队列,这样运行时就不会影响订单,我做了一个小测试,但不能使其正常工作。

I tried using a while not co.done() loop, but it seems to only resolve after the task finishes 我尝试使用了一段时间而不是co.done()循环,但是它似乎只能在任务完成后解决

I tried doing it outside a loop, but for some reason it completes all of the tasks with just one q.get() 我尝试在循环外执行此操作,但是由于某种原因,它仅用一个q.get()就完成了所有任务。

import asyncio
from time import gmtime, strftime 

async def task(name, time, queue=None):

    print(strftime("%H:%M:%S", gmtime()))
    await asyncio.sleep(time)
    print("task %s done"%(name))
    print(strftime("%H:%M:%S", gmtime()))

    if queue:

        queue.task_done()

async def main():

    q = asyncio.Queue()
    await q.put(asyncio.create_task(task("A", 3, q)))
    await q.put(asyncio.create_task(task("B", 1, q)))
    await q.put(asyncio.create_task(task("C", 1, q)))

    for i in range(3):

        co = await q.get()
        done, pending = await asyncio.wait({co})

asyncio.run(main())

I was expecting it to complete all the tasks one after another, so the total time would be 5 seconds. 我期望它可以一次又一次地完成所有任务,因此总时间为5秒。 But it runs them concurrently in 3 seconds with B and C finishing first at the same time, then A 2 seconds later. 但是它会在3秒内同时运行它们,B和C首先同时完成,然后A在2秒后完成。

The reason your example is running all three tasks concurrently is because asyncio.create_task() schedules the coroutines to run even before you pop them off the queue and await them. 您的示例同时运行所有三个任务的原因是因为asyncio.create_task()安排协程运行,甚至在您将协程弹出队列并await它们之前也是如此。 If I'm understanding correctly, the calls to asyncio.create_task() here are unnecessary (as is the call to asyncio.wait() ). 如果我理解正确的话,调用asyncio.create_task()这里是不必要的(因为是调用asyncio.wait() You could simply refactor your main() function like this, and it will run the tasks in FIFO order, and only one task will be run at a time: 您可以像这样简单地重构main()函数,它将以FIFO顺序运行任务,并且一次只能运行一个任务:

async def main():

    q = asyncio.Queue()
    await q.put(task("A", 3, q))
    await q.put(task("B", 1, q))
    await q.put(task("C", 1, q))

    for i in range(3):

        co = await q.get()
        await co

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM