Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 964
Valentin Avatar asked Jun 20 '16 06:06

Valentin


People also ask

Is aiohttp better than requests?

get is that requests fetches the whole body of the response at once and remembers it, but aiohttp doesn't. aiohttp lets you ignore the body, or read it in chunks, or read it after looking at the headers/status code. That's why you need to do a second await : aiohttp needs to do more I/O to get the response body.

Is aiohttp asgi?

Almost all of the frameworks are ASGI-compatible (aiohttp and tornado are exceptions on the moment).

How do I pass headers in aiohttp?

If you need to add HTTP headers to a request, pass them in a dict to the headers parameter. await session. post(url, data='Привет, Мир!

What is client session aiohttp?

Client session is the recommended interface for making HTTP requests. Session encapsulates a connection pool (connector instance) and supports keepalives by default.


1 Answers

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

like image 111
mgc Avatar answered Oct 20 '22 04:10

mgc