如何在Sanic中使用aiohttp ClientSession?

我想了解在Sanic中使用aiohttp的正确方法是什么.

从aiohttp documentation,我发现以下内容:

Don’t create a session per request. Most likely you need a session per application which performs all requests altogether.
More complex cases may require a session per site, e.g. one for Github and another one for Facebook APIs. Anyway making a session for every request is a very bad idea.
A session contains a connection pool inside. Connection reuse and keep-alive (both are on by default) may speed up total performance.

当我去Sanic文档时,我发现了一个这样的例子:

这是一个例子:

from sanic import Sanic
from sanic.response import json

import asyncio
import aiohttp

app = Sanic(__name__)

sem = None

@app.route("/")
async def test(request):
    """
    Download and serve example JSON
    """
    url = "https://api.github.com/repos/channelcat/sanic"

    async with aiohttp.ClientSession() as session:
         async with sem, session.get(url) as response:
         return await response.json()

app.run(host="0.0.0.0", port=8000, workers=2)

这不是管理aiohttp会话的正确方法……

那么正确的方法是什么?
我应该在应用程序中初始化会话并将会话注入所有层中的所有方法吗?

我找到的唯一问题是this,但这没有用,因为我需要创建自己的类来使用会话,而不是sanic.
在Sanic文档中也找到了this,它说你不应该在eventloop之外创建一个会话.

我有点困惑 :(
什么是正确的方法?

解决方法:

为了使用单个aiohttp.ClientSession,我们只需要实例化一次会话,并在应用程序的其余部分中使用该特定实例.

为了实现这一点,我们可以使用before_server_start listener,这将允许我们在应用程序提供第一个字节之前创建实例.

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.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)

代码细分:

>我们正在创建一个aiohttp.ClientSession,将Sanic应用程序在开始时创建的循环作为参数传递,在此过程中避免使用this pitfall.
>我们将该会话存储在Sanic应用程序中.
>最后,我们正在使用此会话来提出请求.

上一篇:Python asyncio / aiohttp:ValueError:Windows上select()中的文件描述符太多


下一篇:单线程+异步协程