Sanic: Reusing aiohttp.ClientSession

Created on 4 Feb 2017  路  3Comments  路  Source: sanic-org/sanic

Hi,

Using Sanic as a frontend on my API server, I managed to reuse a aiohttp.ClientSession instance by passing it as an argument to Sanic HTTPMethodView subclasses with sanic 0.2.0. I also passed the loop explicitly.

However, with Sanic 0.3.0 I get the following error: 'Timeout context manager should be used inside a task'

Apparently, I have to fall back to instantiating the ClientSession on each request, as in the aiohttp_example.py.

Is there any recommended way to reuse the ClientSession object across requests, since it is quite expensive to initialise them?

Thanking you in advance,
Wouter

Most helpful comment

Thanks @ctlaltdefeat,

I solved the issue with the following setup:

handlers.py:

from sanic.views import HTTPMethodView
from sanic.response import json


async def fetch(session, url):
    async with session.get(url) as response:
        return await response.json()


class TestView(HTTPMethodView):

    def __init__(self, session=None):
        self.session = session

    async def get(self, request):
        url = "https://api.github.com/repos/channelcat/sanic"

        response = await fetch(self.session, url)
        return json(response)

app.py:

import aiohttp
from sanic import Sanic
from handlers import TestView


def init(app, loop):
    session = aiohttp.ClientSession(loop=loop)
    app.add_route(TestView.as_view(session=session), '/')


app = Sanic()

app.run(
    host='0.0.0.0',
    port=8000,
    before_start=init,
)

All 3 comments

What version of Python are you using? I was experiencing a similar problem on 3.5 but after upgrading to 3.6 and not passing the loop explicitly it seemed to resolve itself.

I was getting the same error (on 3.6 too).
What I did was to initialize it (together with other things that attach to the event loop) in a function that is set to be called before the server starts. There is a relevant parameter for this in the run function.

Thanks @ctlaltdefeat,

I solved the issue with the following setup:

handlers.py:

from sanic.views import HTTPMethodView
from sanic.response import json


async def fetch(session, url):
    async with session.get(url) as response:
        return await response.json()


class TestView(HTTPMethodView):

    def __init__(self, session=None):
        self.session = session

    async def get(self, request):
        url = "https://api.github.com/repos/channelcat/sanic"

        response = await fetch(self.session, url)
        return json(response)

app.py:

import aiohttp
from sanic import Sanic
from handlers import TestView


def init(app, loop):
    session = aiohttp.ClientSession(loop=loop)
    app.add_route(TestView.as_view(session=session), '/')


app = Sanic()

app.run(
    host='0.0.0.0',
    port=8000,
    before_start=init,
)
Was this page helpful?
0 / 5 - 0 ratings

Related issues

aiurlano picture aiurlano  路  4Comments

eseglem picture eseglem  路  4Comments

geekpy picture geekpy  路  4Comments

ubergarm picture ubergarm  路  4Comments

litelife picture litelife  路  3Comments