Skip to content Skip to sidebar Skip to footer

Why Do Most Asyncio Examples Use Loop.run_until_complete()?

I was going through the Python documentation for asyncio and I'm wondering why most examples use loop.run_until_complete() as opposed to Asyncio.ensure_future(). For example: https

Solution 1:

run_until_complete is used to run a future until it's finished. It will block the execution of code following it. It does, however, cause the event loop to run. Any futures that have been scheduled will run until the future passed to run_until_complete is done.

Given this example:

import asyncio

async def do_io():
    print('io start')
    await asyncio.sleep(5)
    print('io end')

async def do_other_things():
    print('doing other things')

loop = asyncio.get_event_loop()

loop.run_until_complete(do_io())
loop.run_until_complete(do_other_things())

loop.close()

do_io will run. After it's complete, do_other_things will run. Your output will be:

io start
ioend
doing other things

If you schedule do_other_things with the event loop before running do_io, control will switch from do_io to do_other_things when the former awaits.

loop.create_task(do_other_things())
loop.run_until_complete(do_io())

This will get you the output of:

doing other things
io start
ioend

This is because do_other_things was scheduled before do_io. There are a lot of different ways to get the same output, but which one makes sense really depends on what your application actually does. So I'll leave that as an exercise to the reader.

Solution 2:

I think most people didn't understand create_task. when you create_task or ensure_future, it will be scheduled already.

asyncdefsay_after(delay, what):
    await asyncio.sleep(delay)
    print(what)

asyncdefmain():
    task1 = asyncio.create_task(
        say_after(1, 'hello')) # not block here

    task2 = asyncio.create_task(
        say_after(2, 'world'))

    print(f"started at {time.strftime('%X')}") # time0await task1 # block here!print(f"finished at {time.strftime('%X')}") 
    
    await task2 # block here!print(f"finished at {time.strftime('%X')}")

asyncio.run(main())

result is

time0print hello 
time0+1print world 
time0+2

but IF YOU DON'T AWAIT task1, do something else

asyncdefmain():
    task1 = asyncio.create_task(
        say_after(1, 'hello')) # not block hereprint(f"finished at {time.strftime('%X')}") # time0await asyncio.sleep(2) # not await task1print(f"finished at {time.strftime('%X')}") # time0+2
 

asyncio.run(main())

it will do task1 STILL

time0print hello
time0+2

Post a Comment for "Why Do Most Asyncio Examples Use Loop.run_until_complete()?"