Search code examples
pythonasynchronousaiohttp

How to run async process from handler in aiohttp


I'm trying to understand how to run an asynchronous process from coroutine handler within aioweb framework. Here is an example of code:

def process(request):
    # this function can do some calc based on given request
    # e.g. fetch/process some data and store it in DB
    # but http handler don't need to wait for its completion

async def handle(request):
    # process request
    process(request) ### THIS SHOULD RUN ASYNCHRONOUSLY

    # create response
    response_data = {'status': 'ok'}

    # Build JSON response
    body = json.dumps(response_data).encode('utf-8')
    return web.Response(body=body, content_type="application/json")

def main():
    loop = asyncio.get_event_loop()
    app = web.Application(loop=loop)
    app.router.add_route('GET', '/', handle)

    server = loop.create_server(app.make_handler(), '127.0.0.1', 8000)
    print("Server started at http://127.0.0.1:8000")
    loop.run_until_complete(server)
    try:
       loop.run_forever()
    except KeyboardInterrupt:
       pass

if __name__ == '__main__':
   main()

I want to run process function asynchronously from the handler. Can someone provide an example how I can achieve that. I'm struggle to understand how I can pass/use main event loop within a handler and pass it around to another function which by itself can run async process within it.


Solution

  • I guess you should define your existing process function as a coroutine (async def should do the job to wrap your function as a coroutine) and use asyncio.ensure_future in your main handle function.

    async def process(request):
        # Do your stuff without having anything to return
    
    async def handle(request):
        asyncio.ensure_future(process(request))
        body = json.dumps({'status': 'ok'}).encode('utf-8')
        return web.Response(body=body, content_type="application/json")
    

    According to asyncio documention the ensure_future method should schedule the execution of the coroutine (the process function in your case) without blocking/waiting for a result.

    I guess what you are looking for could be related to some existing posts like this one : "Fire and forget" python async/await