正确理解requests库的requests.Session()
request库的底层调用逻辑:
最开始不理解requests.request() 和 requests.Session().request()方法时, 百度一下,发现很多讲的不够清楚,不够透彻. 可以说越讲越糊涂.
===============================================================
requests库发送请求的方式:
requests.get(url, params=None, **kwargs) requests.post(url, data=None, json=None, **kwargs) requests.put(url, data=None, **kwargs) requests.delete(url, **kwargs)
以上方法中返回的是如下方法
requests.request("get", url, params=params, **kwargs) requests.request("post", url, data=data, json=json, **kwargs) requests.request("put", url, data=data, **kwargs) requests.request("delete", url, **kwargs)
即底层调用的是如下方法:
requests.request(method, url, **kwargs)
如下是 requests.request()方法:
def request(method, url, **kwargs): with sessions.Session() as session: return session.request(method=method, url=url, **kwargs)
如上可以看出 requests.request() 方法调用了 sessions.py模块中的Session类的request方法
sessions.py模块中的Session类的request方法具体内容:
def request( self, method, # 请求方法 url, # 请求地址 params=None, # get请求入参 data=None, # post 或 put 请求入参 headers=None, # 请求头 cookies=None, # Cookie files=None, # 文件上传 auth=None, # 鉴权 timeout=None, # 超时处理 allow_redirects=True, # 是否允许重定向 proxies=None, # 是否设置代理 hooks=None, # 钩子 stream=None, # 文件下载 verify=None, # 证书验证 cert=None, # CA认证 json=None, # post请求传参的一种方式 ): """Constructs a :class:`Request <Request>`, prepares it and sends it. Returns :class:`Response <Response>` object. # Create the Request. req = Request( method=method.upper(), url=url, headers=headers, files=files, data=data or {}, json=json, params=params or {}, auth=auth, cookies=cookies, hooks=hooks, ) prep = self.prepare_request(req) proxies = proxies or {} settings = self.merge_environment_settings( prep.url, proxies, stream, verify, cert ) # Send the request. send_kwargs = { "timeout": timeout, "allow_redirects": allow_redirects, } send_kwargs.update(settings) resp = self.send(prep, **send_kwargs) return resp
requests库中的Session类是一个会话对象. 它可以在多个请求之间保持一些参数和状态,即自动关联cookie。通过创建一个Session对象,可以在该对象上执行多个请求,这样可以更有效地利用网络资源。
那么这样说来, 几种方式底层都一样, 都会自动关联cookie. 为什么在一个测试类中既有登录接口用例,又有其他接口用例. 我们执行时, 登录接口已经请求成功, 但是后面的接口请求返回的结果是 403 或者 未登录呢 ? 原因是 虽然requests.Session() 可以自动关联cookie, 但是 两个接口使用的并不是同一个requests.Session()对象. 所以他们之间是独立的请求. 是没有关联关系的. 怎么办呢, 这就需要我们创建一个session对象: session = requests.Session() . 并统一使用该session对象发送请求: session.request(method,url,**kwargs). 这样用例中的请求就在一个会话中. 如 : 在登录之后, cookie信息就存在session对象中,后续的接口请求依然使用该session对象来发送请求, 就可以发送成功.
import requests class SendRequest: ''' 定义一个发送请求的类 ''' """ web项目的接口都存在cookie关联. 使用requests.Session()对象来统一发送请求会自动关联所有请求的cookie信息. requests.Session().request()基于http长连接sokcet,保留历史请求的状态,这就对依赖于登陆状态的二次请求提供了很便利的途径 """ s = requests.Session() # 创建一个session对象( 类变量 ). def send_request(self,method,url,**kwargs): ''' 封装一个统一请求.
为什么??? 所有请求都调用该方法发送, 而该方法是使用上面创建的session对象发送. 这样所有的请求是使用该session对象发送. 这样多个请求都会保持在一个会话中. ''' try: res = SendRequest.s.request(method,url,verify=False,**kwargs) # 调用类变量: 类名.类变量 except Exception as e: raise e.args else: return res
import json import pprint from Slience.utils.request_util import SendRequest class Test001: def setup_class(self): # 登录 method = 'post' url = 'http://127.0.0.1/api/mgr/signin' userinfo = {'username': 'byhy', 'password': '88888888'} # 使用同一个session对象发送请求, 保持在一个会话中 res = SendRequest().send_request(method,url,data=userinfo) # print(res.json()) return res def test_search_customer(self): # 查询客户 method = 'GET' url = 'http://127.0.0.1/api/mgr/customers' data = { "action": "list_customer", "pagesize": 100, "pagenum": 1, "keywords": "人民医院" } # 使用同一个session对象发送请求, 保持在一个会话中 res = SendRequest().send_request(method, url, params=data) print(json.dumps(res.json(),ensure_ascii=False,indent=4)) return res def test_search_medicines(self): # 查询药品 method = 'GET' url = 'http://127.0.0.1/api/mgr/medicines' data = { "action": "list_medicine", "pagesize": 100, "pagenum": 1, "keywords": "" } # 使用同一个session对象发送请求, 保持在一个会话中 res = SendRequest().send_request(method, url, params=data) pprint.pprint(res.json()) return res def teardown_class(self): ''' 关闭会话 ''' SendRequest.s.close()
阅读资料:
Python的requests库中的Session类是一个会话对象,它可以在多个请求之间保持一些参数和状态。通过创建一个Session对象,可以在该对象上执行多个请求,这样可以更有效地利用网络资源。
使用Session对象可以做到以下几点:
1. 自动管理cookies:Session对象会自动处理请求和响应中的cookies,可以自动保存和发送cookies,无需手动处理。
2. 保持参数和状态:Session对象可以在多个请求之间保持一些参数和状态,例如HTTP头、身份验证信息等。这样可以避免在每个请求中重复设置这些参数。
3. 使用连接池:Session对象使用底层的urllib3库,可以使用连接池来管理和重用HTTP连接,提高性能。
使用Session对象的一般流程如下:
1. 创建一个Session对象:session = requests.Session()
2. 使用Session对象发送请求:response = session.get(url)
3. 处理响应:可以像使用requests库一样处理响应,例如获取响应内容、状态码等。
4. 使用Session对象发送其他请求:可以继续使用session对象发送其他请求,它会自动处理cookies和其他参数。
5. 关闭会话:session.close(),如果不主动关闭,会话会一直保持。
总之,Session对象可以方便地管理HTTP会话,提高请求的性能和灵活性。