5

I have what is probably a quite useless question, but nevertheless I feel I am missing something that might be important to understand how asyncio works.

I just started to familiarize with asyncio and I wrote this very basic piece of code:

import asyncio
import datetime
from random import randint


async def coroutine(i):
    start = datetime.datetime.now()
    print('coroutine {} started.'.format(i))
    n = randint(1, 11)
    await asyncio.sleep(n)
    end = datetime.datetime.now()
    print('coroutine {} finished after {} with random = {}.'.format(i, (end-start).seconds, n))
    return i


def simple():
    loop = asyncio.get_event_loop()
    cors = [coroutine(x) for x in range(20)]
    loop.run_until_complete(asyncio.wait(cors))


if __name__ == '__main__':
    simple()

This is one result I got:

coroutine 3 started.
coroutine 9 started.
coroutine 15 started.
coroutine 4 started.
coroutine 10 started.
coroutine 16 started.
coroutine 1 started.
coroutine 5 started.
coroutine 11 started.
coroutine 17 started.
coroutine 2 started.
coroutine 6 started.
coroutine 12 started.
coroutine 18 started.
coroutine 0 started.
coroutine 7 started.
coroutine 13 started.
coroutine 19 started.
coroutine 8 started.
coroutine 14 started.
coroutine 7 finished after 1 with random = 1.
coroutine 12 finished after 2 with random = 2.
coroutine 3 finished after 3 with random = 3.
coroutine 5 finished after 3 with random = 3.
coroutine 0 finished after 3 with random = 3.
coroutine 10 finished after 4 with random = 4.
coroutine 17 finished after 4 with random = 4.
coroutine 2 finished after 5 with random = 5.
coroutine 16 finished after 6 with random = 6.
coroutine 18 finished after 6 with random = 6.
coroutine 15 finished after 7 with random = 7.
coroutine 9 finished after 8 with random = 8.
coroutine 1 finished after 8 with random = 8.
coroutine 6 finished after 8 with random = 8.
coroutine 11 finished after 9 with random = 9.
coroutine 8 finished after 9 with random = 9.
coroutine 4 finished after 10 with random = 10.
coroutine 13 finished after 10 with random = 10.
coroutine 19 finished after 10 with random = 10.
coroutine 14 finished after 10 with random = 10.

Now, my question is: why on earth the coroutines start in a scrambled order? I was expecting to see an ordered "coroutine x started" message, from coroutine 0 to coroutine 20...only then I assumed they would scramble due to the randomized sleep time...what am I missing?

1 Answer 1

1

The order is undetermenistic by .wait() specification.

You shouldn't care about it.

Actually all coroutines are started at the same loop iteration, almost at the same time.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for replying. Could you please link me a reference to the specification that mentions that .wait() is undeterministic? I have been searching quite a lot for such a hint without any luck! Also the docstring is quite minimal.
Well, it was never stated explicitly but nothing guarantee any order too. See also very similar question about gather()
@AndrewSvetlov what if the order matters? Let's say you want 2 coroutines to run concurrently but coroutine A needs to run first to add a variable to the work environment so that coroutine B can use it.
await func1(); await func2() is simple and obvious answer

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.