Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run two async functions without blocking each other

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

like image 509
fsinisi90 Avatar asked Oct 12 '18 20:10

fsinisi90


People also ask

Can two async functions run at the same time?

In order to run multiple async/await calls in parallel, all we need to do is add the calls to an array, and then pass that array as an argument to Promise. all() . Promise. all() will wait for all the provided async calls to be resolved before it carries on(see Conclusion for caveat).

How do I run two async functions simultaneously in Python?

To do so we have to create a new async function (main) and call all the async functions (which we want to run at the same time) in that new function (main). And then call the new (main) function using Event Loops… Code: Python3.

How do two parallel calls without blocking each other?

await Promise. all([someCall(), anotherCall()]); as already mention will act as a thread fence (very common in parallel code as CUDA), hence it will allow all the promises in it to run without blocking each other, but will prevent the execution to continue until ALL are resolved.

Do async functions run synchronously?

Synchronous code inside an async function runs synchronously. The interpreter will only move on to the next line after the call of the async function (here, the console. log("b"); ) after all synchronous code has finished - for example, if it runs into an await .


1 Answers

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(...).

like image 143
JohanL Avatar answered Oct 09 '22 18:10

JohanL