一些函数和类可以帮助您处理aiohttp会话

aiohttp-asynctools的Python项目详细描述


Travis status

自动将会话管理添加到类

一些函数和类可以帮助您处理aiohttp客户端会话。这是在这个discussion之后制作的。这适用于修饰协同路由和异步生成器方法。

安装

pip install aiohttp-asynctools

tl;dr

通过以下4个步骤,快速、干净地向类中添加aiohttp.ClientSession对象:

  1. 导入异步工具
  2. 扩展AsyncTools.AbstractSessionContainer
  3. (可选)在__init__方法中剪切会话实例。
  4. @asynctools.attach_session修饰异步方法/生成器以附加session参数。

下面是一个使用数学api(http://api.mathjs.org/v4)的简单示例的样子:

importasyncioimportasynctools# 1.classMathRequests(asynctools.AbstractSessionContainer):# 2.def__init__(self):super().__init__(raise_for_status=True)# 3. (optional)@asynctools.attach_session# 4.asyncdefget_text(self,url,params,session=None):asyncwithsession.get(url,params=params)asresponse:returnawaitresponse.text()asyncdefget_square(self,value):returnawaitself.get_text("http://api.mathjs.org/v4",params={'expr':'{}^2'.format(value)})

注意__init__方法必须在这里,如果它是空的,只需使用pass关键字作为其内容。

现在,您已经准备好实例化一个MathRequests上下文管理器,并开始使用单个aiohttpsession请求数学服务(会话对MathRequests用户隐藏):

fromaiohttpimportwebroutes=web.RouteTableDef()@routes.get('/squares')asyncdefindex(request):tasks=[]data=request.queryvalues=data['values'].split(',')# Use the object as a context manager (async with <context_manager> as <name>)asyncwithMathRequests()asmaths:results=awaitasyncio.gather(*[maths.get_square(v)forvinvalues])returnweb.json_response({'values':values,'results':results})maths_app=web.Application()maths_app.add_routes(routes)

您也可以显式地启动/关闭会话:

# ...maths.start_session()results=awaitasyncio.gather(*[maths.get_square(v)forvinvalues])maths.close_session()# ...

现在,您可以启动服务器并测试服务(这里的gunicorn示例):

gunicorn math_requests:maths_app --bind localhost:8085 --worker-class aiohttp.GunicornWebWorker --reload
curl 'http://localhost:8085/squares?values=1,2,3,4,5,6,7,8,9,10'

哪个应该输出:

{"values":["1","2","3","4","5","6","7","8","9","10"],"results":["1","4","9","16","25","36","49","64","81","100"]}

详细信息和说明

什么?

目标是帮助aiohttp用户以高效/干净的方式构建包含sessions对象的类。

为什么?

如果要构建使用aiohttp client发出请求的类,则在某些时候必须处理会话。 quickstart guide for aiohttp client有一个关于会话的重要注释。

importaiohttpasyncwithaiohttp.ClientSession()assession:asyncwithsession.get('http://httpbin.org/get')asresp:print(resp.status)print(awaitresp.text())

...

Note

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 other one for Facebook APIs. Anyway making a session for every request is a very bad idea.

A session contains a connection pool inside. Connection reusage and keep-alives (both are on by default) may speed up total performance.

我们的目标是将一个会话附加到一个给定的对象上,在这个模块中,您只需要4行(非常简单)代码就可以简单地实现这个目标。

怎么做?

<>模块提供了一个抽象类^ {< CD11>}和一个方法装饰器{{CD12}},您必须使用它来自动将会话管理添加到现有的类中。

假设您有一个类MathRequests,它有一个方法get_square,使用位于http://api.mathjs.org/v4的math api服务的aiohttp.get请求返回给定参数的平方值。以下是您的班级目前的情况:

importasyncio,aiohttproutes=aiohttp.web.RouteTableDef()classMathRequests:asyncdefget_text(self,url,params):# Remember "making a session for every request is a very bad idea"asyncwithaiohttp.ClientSession()assession:asyncwithsession.get(url,params=params)asresponse:returnawaitresponse.text()asyncdefget_square(self,value):returnawaitself.get_text("http://api.mathjs.org/v4",params={'expr':'{}^2'.format(value)})@routes.get('/squares')asyncdefindex(request):tasks=[]data=request.queryvalues=data['values'].split(',')maths=MathRequests()results=awaitasyncio.gather(*[maths.get_square(v)forvinvalues])returnweb.json_response({'values':values,'results':results})maths_app=aiohttp.web.Application()maths_app.add_routes(routes)

正如aiohttp文档所说,这样实现MathRequests是个坏主意,我们需要为所有get_square请求共享一个会话。

一个简单的解决方案是在MathRequests中存储一个客户端会话对象,您可以在__init__方法中启动它。不幸的是,这不是一个非常干净的解决方案,因为aiohttp会话应该以同步的方式实例化(在偶数循环之外)。有关在coroutine之外创建会话的更多信息,请参见aiohttp#1468

下面是使用提供的模块的最终解决方案asynctools

importasyncioimportasynctools# 1) Import# 2) Extends the abstract class that will handle the aiohttp session for you:classMathRequests(asynctools.AbstractSessionContainer):def__init__(self):# 2') (optional) initilise with any 'aiohttp.ClientSession' argumentsuper().__init__(raise_for_status=True)# 3) This decorator will automatically fill the session argument:@asynctools.attach_sessionasyncdefget_text(self,url,params,session=None):# 4) Add the 'session' argumentasyncwithsession.get(url,params=params)asresponse:returnawaitresponse.text()asyncdefget_square(self,value):returnawaitself.get_text("http://api.mathjs.org/v4",params={'expr':'{}^2'.format(value)})fromaiohttpimportwebroutes=web.RouteTableDef()@routes.get('/squares')asyncdefindex(request):tasks=[]data=request.queryvalues=data['values'].split(',')asyncwithMathRequests()asmaths:# Use the object as a context manager (async with <context_manager> as <name>)results=awaitasyncio.gather(*[maths.get_square(v)forvinvalues])returnweb.json_response({'values':values,'results':results})maths_app=web.Application()maths_app.add_routes(routes)

使用MathRequests作为context manager是最好的选择(因为它将确保会话正确启动和关闭),但它不是唯一的选择,您还可以保持代码原来的状态:

@routes.get('/squares')asyncdefindex(request):tasks=[]data=request.queryvalues=data['values'].split(',')maths=MathRequests()results=awaitasyncio.gather(*[maths.get_square(v)forvinvalues])returnweb.json_response({'values':values,'results':results})

在这种情况下,没有会话附加到maths对象,对get_square的每个调用都将使用不同的会话(这与旧版本的MathRequests一样糟糕)。要避免这种情况,可以做的是显式地打开一个“数学会话”,它将使所有的get_square调用使用同一会话(同时,完成后不要忘记关闭会话):

@routes.get('/maths')asyncdefindex(request):tasks=[]data=request.queryvalues=data['values'].split(',')maths=MathRequests()maths.start_session()results=awaitasyncio.gather(*[maths.get_square(v)forvinvalues])maths.close_session()returnweb.json_response({'values':values,'results':results})

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java传递实现接口的内部类   java为什么managedbean方法在post请求中的过滤器调用之前调用   java Android应用程序在Android M,O上崩溃,登录A/libc时出错:tid 17938中的致命信号11(SIGSEGV),代码2,故障地址0x343a2944   java JPA存储库。findByAll()返回null,但数据库中存在所有内容   用于发送电子邮件的java Ant脚本   Java小程序HTML页面发生了奇怪的事情   在Postman的请求正文中传递多个JSON数据,并使用Jersy(JXRS)进入Java Rest API   无法强制转换java DAO类   10分钟后重新连接java   正则表达式如何在java中选择字符串直到某个字符   java我的输出有一些问题   Objective中的java时间段   java如何在新屏幕上基于按钮单击在webview中打开url   java哪个selenium版本与Firefox ESR 45.2.0兼容   java无法使用Apache Camel 3.1.0将XML转换为JSON