Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call async function from sync function, while the synchronous function continues : Python

After perusing many docs on AsyncIO and articles I still could not find an answer to this : Run a function asynchronously (without using a thread) and also ensure the function calling this async function continues its execution.

Pseudo - code :

async def functionAsync(p):
    #...
    #perform intensive calculations
    #...
    print ("Async loop done")

def functionNormal():
    p = ""
    functionAsync(p)
    return ("Main loop ended")

 print ("Start Code")
 print functionNormal()

Expected Output :

Start code
Main loop ended
Async loop done

Searched examples where loop.run_until_complete is used, but that will not return the print value of functionNormal() as it is blocking in nature.

like image 524
Shivansh Jagga Avatar asked Apr 12 '19 08:04

Shivansh Jagga


People also ask

Can we call async method in sync method?

Use the Result property on the asynchronous Task, like so: // Synchronous method. void Method()

How do you call async function in Python?

To run an async function (coroutine) you have to call it using an Event Loop. Event Loops: You can think of Event Loop as functions to run asynchronous tasks and callbacks, perform network IO operations, and run subprocesses. Example 1: Event Loop example to run async Function to run a single async function: Python3.

Is Python asynchronous or synchronous?

There are two basic types of methods in the Parallels Python API: synchronous and asynchronous. When a synchronous method is invoked, it completes executing before returning to the caller. An asynchronous method starts a job in the background and returns to the caller immediately.

How do I run async without await in Python?

One way would be to use create_task function: import asyncio async def handler_message(request): ... loop = asyncio. get_event_loop() loop. create_task(perform_message(x,y,z)) ...


2 Answers

asyncio can't run arbitrary code "in background" without using threads. As user4815162342 noted is asyncio you run event loop that blocks main thread and manages execution of coroutines.

If you want to use asyncio and take advantage of using it, you should rewrite all your functions that uses coroutines to be coroutines either up to main function - entry point of your program. This main coroutine is usually passed to run_until_complete. This little post reveals this topic in more detail.


Since you're interested in Flask, take a look Quart: it's a web framework that tries to implement Flask API (as much as it's possible) in terms of asyncio. Reason this project exists is because pure Flask isn't compatible with asyncio. Quart is written to be compatible.

If you want to stay with pure Flask, but have asynchronous stuff, take a look at gevent. Through monkey-patching it can make your code asynchronous. Although this solution has its own problems (which why asyncio was created).

like image 178
Mikhail Gerasimov Avatar answered Nov 10 '22 00:11

Mikhail Gerasimov


Maybe it's a bit late, but I'm running into a similar situation and I solved it in Flask by using run_in_executor:

def work(p):
    # intensive work being done in the background


def endpoint():
    p = ""
    loop = asyncio.get_event_loop()
    loop.run_in_executor(None, work, p)

I'm not sure however how safe this is since the loop is not being closed.

like image 37
akch Avatar answered Nov 10 '22 01:11

akch