Complete newb here, reading about Asycnio Tasks which has this example:
import asyncio
import time
async def say_after(delay, what):
    await asyncio.sleep(delay)
    print(what)
async def main():
    task1 = asyncio.create_task(
        say_after(1, 'hello'))
    task2 = asyncio.create_task(
        say_after(2, 'world'))
    print(f"started at {time.strftime('%X')}")
    # Wait until both tasks are completed (should take
    # around 2 seconds.)
    await task1
    await task2
    print(f"finished at {time.strftime('%X')}")
asyncio.run(main())
My original understanding of await is that it blocks the execution of current function and wait for the async function to return.
But in this case both coroutines are executed concurrently, it doesn't fit well my understanding of await. Could someone please explain?
Further investigation, by adding extra print in say_after, it seems to me the coroutine doesn't start until await happens...
import asyncio
import time
async def say_after(delay, what):
    print('Received {}'.format(what))
    await asyncio.sleep(delay)
    print(what)
async def main():
    task1 = asyncio.create_task(
        say_after(1, 'hello'))
    task2 = asyncio.create_task(
        say_after(2, 'world'))
    print(f"started at {time.strftime('%X')}")
    # Wait until both tasks are completed (should take
    # around 2 seconds.)
    await task1
    await task2
    print(f"finished at {time.strftime('%X')}")
asyncio.run(main())
prints
started at 13:41:23
Received hello
Received world
hello
world
finished at 13:41:25
 
     
    