Reputation: 462
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.
#!/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()
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!
Upvotes: 0
Views: 493
Reputation: 19332
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!
Upvotes: 0
Reputation: 365597
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)
Upvotes: 1