async function in Python, basic example

Viewed 48

Can you help me see what I have understood wrong here please. I have two functions and I would like the second one to run regardless of the status of the first one (whether it is finished or not). Hence I was thinking to make the first function asynchronous. This is what I have done

import os
import asyncio
from datetime import datetime

async def do_some_iterations():
    for i in range(10):
        print(datetime.now().time())
        await asyncio.sleep(1)
    print('... Cool!')


async def main():
    task = asyncio.create_task (do_some_iterations())
    await task

def do_something():
    print('something...')


if __name__ == "__main__":
    asyncio.run(main())
    do_something()

The output is:

00:46:00.145024
00:46:01.148533
00:46:02.159751
00:46:03.169868
00:46:04.179915
00:46:05.187242
00:46:06.196356
00:46:07.207614
00:46:08.215997
00:46:09.225066
 Cool!
something...

which looks like the traditional way where one function has to finish and then move to the next call.

I was hoping instead to execute do_something() before the asynchronous function started generating the print statements (or at lease at the very top of those statements..)

What am I doing wrong please? How I should edit the script?

1 Answers

They both need to be part of the event loop the you created. asyncio.run() itself is not async, which means it will run until the loop ends. One easy way to do this is to use gather()

import asyncio
from datetime import datetime

async def do_some_iterations():
    for i in range(10):
        print(datetime.now().time())
        await asyncio.sleep(1)
    print('... Cool!')

async def do_something():
    print('something...')

async def main():
    await asyncio.gather(
        do_some_iterations(),
        do_something()
    )

if __name__ == "__main__":
    asyncio.run(main())
    print("done")

This will print:

16:08:38.921879
something...
16:08:39.922565
16:08:40.923709
16:08:41.924823
16:08:42.926004
16:08:43.927044
16:08:44.927877
16:08:45.928724
16:08:46.929589
16:08:47.930453
... Cool!
done

You can also simply add another task:

async def main():
    task = asyncio.create_task(do_some_iterations())
    task2 = asyncio.create_task(do_something())

In both cases the function needs to be awaitable.

Related