12

I have an async function and I want to run another one "in parallel". But I need to do it at a certain moment inside that first function.

I've seen a lot of examples, but all of them were launching two functions at the same time, and that's not what I want.

I've created this simple example to illustrate what I want to achieve (and what I've tried):

import asyncio
import time

async def print_letters():
    for letter in ['A', 'B', 'C', 'D']:
        print(letter)
        time.sleep(1)

async def print_numbers(loop):
    for number in range(1, 7):
        if(number == 3):
            # same result with create_task
            # loop.create_task(print_letters())
            asyncio.ensure_future(print_letters())
        print(number)
        time.sleep(1)

loop = asyncio.get_event_loop()
loop.run_until_complete(print_numbers(loop))
print('End')

The current output:

1, 2, 3, 4, 5, 6, A, B, C, D, End

The desired output would be something like this:

1, 2, 3, A, 4, B, 5, C, 6 D, End

I've tried some other stuff (asyncio.wait, for example) but none worked as expected. Also the documentation it's not easy to understand when you're pretty new with Python asyncio.

If the question is unclear or there's something missing, let me know so I can edit it. I appreciate any kind of help.

Python 3.6.2

fsinisi90
  • 1,138
  • 1
  • 16
  • 45

1 Answers1

11

You need your asynchronous functions to yield the CPU while waiting, so that other asynchronous functions get a chance to run. Yielding the CPU is done, using the await keyword. In addition you need to use the sleep(...) funtion defined in asyncio as the normal time.sleep(...) does not allow re-entry into the yielded funtion. All-in-all, this requires your program to be

import asyncio

async def print_letters():
    for letter in ['A', 'B', 'C', 'D']:
        print(letter)
        await asyncio.sleep(1)

async def print_numbers(loop):
    for number in range(1, 7):
        if(number == 3):
            # same result with create_task
            # loop.create_task(print_letters())
            asyncio.ensure_future(print_letters())
        print(number)
        await asyncio.sleep(1)

loop = asyncio.get_event_loop()
loop.run_until_complete(print_numbers(loop))
print('End')

Thus, all you practically have to do, is replace time.sleep(...) with await asyncio.sleep(...).

JohanL
  • 6,671
  • 1
  • 12
  • 26