首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Sanic中使用ClientSession?

如何在Sanic中使用ClientSession?
EN

Stack Overflow用户
提问于 2018-08-01 16:38:12
回答 2查看 4.7K关注 0票数 7

我正在试图理解什么是正确的方式,使用aiohttp与Sanic。

在aiohttp 文档上,我发现了以下内容:

不为每个请求创建一个会话。很可能每个应用程序都需要一个会话来执行所有请求。更复杂的情况可能需要每个站点进行一次会话,例如,一个用于Github,另一个用于Facebook。无论如何,为每个请求设置一个会话是一个非常糟糕的主意。会话中包含一个连接池。连接重用和保持活动(在默认情况下都是打开的)可能会加快总体性能。

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

这就是一个例子:

代码语言:javascript
复制
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会话的正确方法..。

那么正确的方法是什么呢?

我应该在应用程序中插入一个会话并将会话注入到所有层的所有方法中吗?

我发现的唯一问题是,但这没有帮助,因为我需要自己的类来使用会话,而不是sanic。

还在Sanic文档中找到了,其中说您不应该在事件循环之外创建会话。

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-11-08 10:10:38

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

为了实现这一点,我们可以使用一个监听程序,它允许我们在应用程序服务第一个字节之前创建实例。

代码语言:javascript
复制
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)

代码的分解:

  • 我们正在创建一个aiohttp.ClientSession,作为参数传递Sanic应用程序在开始时创建的循环,避免在过程中使用这个陷阱
  • 我们将该会话存储在Sanic app中。
  • 最后,我们正在利用这次会议提出我们的请求。
票数 13
EN

Stack Overflow用户

发布于 2018-08-01 19:47:51

这基本上就是我在做的事。

我创建了一个模块(interactions.py),它具有如下函数:

代码语言:javascript
复制
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()

然后我就在await上说:

代码语言:javascript
复制
results = await interactions.get(url)

我不知道为何这不是“正确的方式”。会话(至少满足我的需要)可以在我的请求完成后立即关闭。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51638347

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档