Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

calling sync functions from async function

I am in the process of trying to port a flask app to quart to utilise asyncio. I don't think my current approach is working, as my entire function chain is written without async in mind - consider the following:

def long_running_task(task):
    result = some_synchronous_function(task)
    return result

@app.route('/<task>', methods=['GET'])
async def do_task(task):
    ok = await long_running_task(task)
    if ok:
        return (ok.result)
    else:
        return ('Something went wrong')

If long_running_task and its whole chain of function calls are not declared as async, am I actually getting any benefit from my route being declared as async?

like image 832
chris Avatar asked Feb 14 '19 07:02

chris


People also ask

Can async functions call sync functions?

Use Asyncify. asyncify() takes the sync (blocking) function that you want to call and then returns another async function that takes the actual arguments for the original sync function. Once you call that, Asyncer (using AnyIO) will run that function in a way that doesn't block the event loop.

Can we call synchronous method from another asynchronous method?

Yes, We can call a synchronous method inside a future method. Both will run on Asynchronous Only.

Do async functions run synchronously?

Top-level code, up to and including the first await expression (if there is one), is run synchronously. In this way, an async function without an await expression will run synchronously. If there is an await expression inside the function body, however, the async function will always complete asynchronously.

How do I call a function asynchronously 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.


1 Answers

To run a blocking synchronous function from asyncio, without blocking the main event loop, you can use loop.run_in_executor() to run the blocking function in a ThreadPoolExecutor or ProcessPoolExecutor` (i.e. in its own thread or process).

From within the async function you want to call it from:

loop = asyncio.get_event_loop()

result = await loop.run_in_executor(None, long_running_task, task)

The first argument None is to tell it to use the default executor for the loop. Obviously do_task() will still have to wait for result to complete, but while it is waiting, other async tasks will be able to run in event-loop.

like image 141
J. Taylor Avatar answered Oct 20 '22 08:10

J. Taylor