How to use an aiohttp ClientSession with Sanic?

前端 未结 2 813
终归单人心
终归单人心 2021-01-03 10:00

I am trying to understand what is the right way to use aiohttp with Sanic.

From aiohttp documentation, I find the following:

Don’t cr

相关标签:
2条回答
  • 2021-01-03 10:22

    In order to use a single aiohttp.ClientSession we need to instantiate the session only once and use that specific instance in the rest of the application.

    To achieve this we can use a before_server_start listener which will allow us to create the instance before the app serves the first byte.

    from sanic import Sanic 
    from sanic.response import json
    
    import aiohttp
    
    app = Sanic(__name__)
    
    @app.listener('before_server_start')
    def init(app, loop):
        app.aiohttp_session = aiohttp.ClientSession(loop=loop)
    
    @app.listener('after_server_stop')
    def finish(app, loop):
        loop.run_until_complete(app.aiohttp_session.close())
        loop.close()
    
    @app.route("/")
    async def test(request):
        """
        Download and serve example JSON
        """
        url = "https://api.github.com/repos/channelcat/sanic"
    
        async with app.aiohttp_session.get(url) as response:
            return await response.json()
    
    
    app.run(host="0.0.0.0", port=8000, workers=2)
    

    Breakdown of the code:

    • We are creating an aiohttp.ClientSession, passing as argument the loop that Sanic apps create at the start, avoiding this pitfall in the process.
    • We store that session in the Sanic app.
    • Finally, we are using this session to make our requests.
    0 讨论(0)
  • 2021-01-03 10:25

    That is essentially what I am doing.

    I created a module (interactions.py) that has, for example a function like this:

    async def get(url, headers=None, **kwargs):
        async with aiohttp.ClientSession() as session:
            log.debug(f'Fetching {url}')
            async with session.get(url, headers=headers, ssl=ssl) as response:
                try:
                    return await response.json()
                except Exception as e:
                    log.error(f'Unable to complete interaction: {e}')
                    return await response.text()
    

    Then I just await on that:

    results = await interactions.get(url)
    

    I am not sure why that is not the "right way". The session (at least for my needs) can be closed as soon as my request is done.

    0 讨论(0)
提交回复
热议问题