Asyncio getting different outputs

Question:

In the first example I am getting output I expect here to be, but I can’t say same about second example. Technically, in both example I have 3 tasks (Just in second example, I am scheduling 2 coros execution from main coro) isn’t it ? In second example, why Event loop does not resume main() coro in the same fashion as in first example ?

Example 1:

import time
import asyncio

async def coro1():
    while True:
        print('coro1()')
        await asyncio.sleep(0.1) # yield ! Give control back to event loop, to start/resume another task !

async def coro2():
    while True:
        print('coro2()')
        await asyncio.sleep(0.1) # yield ! Give control back to event loop, to start/resume another task !

async def main():
    while True:
        print('main()')
        await asyncio.sleep(0.1) # yield ! Give control back to event loop, to start/resume another task ! 

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    main_task = loop.create_task(main())

    task1 = loop.create_task(coro1()) # Schedule execution of coro !
    task2 = loop.create_task(coro2()) # # Schedule execution of coro !
    
    loop.run_until_complete(main_task)

    loop.close()

Example 1 Output:

main()
coro1()
coro2()
main()
coro1()
coro2()
main()
coro1()
coro2()

Example 2:

import time
import asyncio

async def coro1():
    while True:
        print('coro1()')
        await asyncio.sleep(0.1) # yield ! Give control back to event loop, to start/resume another task !

async def coro2():
    while True:
        print('coro2()')
        await asyncio.sleep(0.1) # yield ! Give control back to event loop, to start/resume another task !

async def main():
    loop = asyncio.get_running_loop()
    task1 = loop.create_task(coro1()) # Schedule execution of coro from main !
    task2 = loop.create_task(coro2()) # Schedule execution of coro from main !
    while True:
        print('main()')
        await task1 # yield ! Give control back to event loop, to start/resume another task ! 
        await task2 # yield ! Give control back to event loop, to start/resume another task ! 

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    main_task = loop.create_task(main())
    loop.run_until_complete(main_task)

    loop.close()

Example 2 output:

main()
coro1()
coro2()
coro1()
coro2()
coro1()
coro2()
Asked By: varuserx

||

Answers:

None of your tasks ever complete, they’ll all continue endlessly. In the first case, each task in itself only awaits asyncio.sleep, which does complete; the code then continues with the next loop iteration.

In your second case, the main task awaits the completion of the coro1() task, before it will continue with its loop. Since coro1 never completes, it is indefinitely stuck at the await task1 line.

Answered By: deceze