一些函数和类可以帮助您处理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 OnClick用于ListView中的特定项   java如何多次循环相同的TestNG测试。包括课前和课后   java如何在Codenameone中设置BrowserComponent浏览器窗口大小   java Socketchannel始终为空   java以编程方式向JavaFX WebEngine历史添加新条目   java Hibernate+Spring与Oracle一起使用分层查询(从+连接方式开始)   Java中的安卓 getView和Beacon(Estimote)问题   计时器如何在java中设置暂停选项   java为什么输入1000000000000的输出不正确?   java如何在程序执行期间更改log4j2中的日志记录级别   java阻止代码引发XML异常   未找到媒体类型为application/json的java JAX RS MessageBodyWriter   java如何将BuffereImage中的特定颜色(0xFF00FF)设置为透明?   java如何列出web元素,如果网页中没有特定链接的id,如何单击网页中的特定链接?   在Java中读取txt文件时获取EOFEException   java如何避免为每个视图添加inject方法?   JavaSpringController:Facebook上类似文章的永久链接   java在尝试执行脚本时遇到错误“net.serentiybdd.core.exceptions.serentitymanagedexception:No session ID”