简体   繁体   中英

Python - How to make tasks run asynchronously using asyncio

I was trying to run 2 tasks at the same time for a single client from the list but it doesn't work as expected - the tasks still ran synchronously (please see Output ). Can you help me understand what's wrong with my code? Thank you.

Code

#!/usr/bin/env python3

import asyncio


async def do_b(client):
    print('{}: doing b...'.format(client))
    await asyncio.sleep(1)
    print('{}: b is done!'.format(client))


async def do_a(client):
    print('{}: doing a...'.format(client))
    await asyncio.sleep(1)
    print('{}: a is done!'.format(client))


async def loop_a():
    clients = ['CLIENT-1', 'CLIENT-2', 'CLIENT-3', 'CLIENT-4', 'CLIENT-5']

    for client in clients:
        task1 = asyncio.ensure_future(do_a(client))
        task2 = asyncio.ensure_future(do_b(client))

        await asyncio.gather(task1, task2)


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(loop_a())
    loop.close()

Output

CLIENT-1: doing a...
CLIENT-1: doing b...
CLIENT-1: a is done!
CLIENT-1: b is done!
CLIENT-2: doing a...
CLIENT-2: doing b...
CLIENT-2: a is done!
CLIENT-2: b is done!
CLIENT-3: doing a...
CLIENT-3: doing b...
CLIENT-3: a is done!
CLIENT-3: b is done!
CLIENT-4: doing a...
CLIENT-4: doing b...
CLIENT-4: a is done!
CLIENT-4: b is done!
CLIENT-5: doing a...
CLIENT-5: doing b...
CLIENT-5: a is done!
CLIENT-5: b is done!

EDIT:

Another question. How do I make it execute like this which does not follow their order in the list? Because currently, CLIENT-1 is being blocked by CLIENT-2 , same as the other clients and I was trying to avoid that. Is this possible?

CLIENT-1: doing a...
CLIENT-2: doing a...
CLIENT-1: doing b...
CLIENT-3: doing a...
CLIENT-1: a is done!
CLIENT-1: b is done!
CLIENT-2: a is done!
CLIENT-3: a is done!
CLIENT-2: doing b...
CLIENT-2: b is done!
CLIENT-3: doing b...
CLIENT-3: b is done!

First, the two tasks aren't running synchronously, as you can see from the fact that doing b... keeps showing up in between doing a... and a is done! .

Each pair of tasks is finishing before the next client starts, but that's because you're explicitly asking for that to happen. If you don't want to await each pair, just… don't await each pair. For example:

futs = []
for client in clients:
    futs.append(asyncio.ensure_future(do_a(client)))
    futs.append(asyncio.ensure_future(do_b(client)))
await asyncio.gather(*futs)

a and b are running at the same time and the output shows that. Clients 1, 2, 3, 4, and 5 are running sequentially because there is an await asyncio.gather between them.

You can merge all of the tasks into one list to make them run at the same time:

async def loop_a():
    clients = ['CLIENT-1', 'CLIENT-2', 'CLIENT-3', 'CLIENT-4', 'CLIENT-5']

    tasks = []
    for client in clients:
        tasks.append(asyncio.ensure_future(do_a(client)))
        tasks.append(asyncio.ensure_future(do_b(client)))
    await asyncio.gather(*tasks)

Now it prints:

CLIENT-1: doing a...
CLIENT-1: doing b...
CLIENT-2: doing a...
CLIENT-2: doing b...
CLIENT-3: doing a...
CLIENT-3: doing b...
CLIENT-4: doing a...
CLIENT-4: doing b...
CLIENT-5: doing a...
CLIENT-5: doing b...
CLIENT-1: a is done!
CLIENT-2: a is done!
CLIENT-3: b is done!
CLIENT-1: b is done!
CLIENT-3: a is done!
CLIENT-2: b is done!
CLIENT-4: a is done!
CLIENT-5: b is done!
CLIENT-4: b is done!
CLIENT-5: a is done!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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