作为客户端使用
aiohttp是一个基于asyncio模块的异步HTTP客户端,所以在使用时,要打开思路,以异步的方式思考问题。
进行基本访问
使用aiohttp模块访问指定URL十分简单,只需要调用相应的HTTP谓词方法即可。基本使用方式如下:
import aiohttp
async with aiohttp.ClientSession() as session:
async with session.get('http://www.baidu.com/') as resp:
print(resp.status)
print(await resp.text())
示例代码中使用ClientSession()
创建了一个用于访问的会话,之后使用这个会话的不同谓词方法来进行HTTP访问,并返回ClientResponse
类型的结果。
会话的调用函数一般会将其排入asyncio.get_event_loop()
中,参考之前并行计算中介绍的使用.run_until_complete()
方法排入异步任务的示例。
在实际使用中,可以在整个应用中使用一个会话,不要对于每次HTTP访问都创建一个会话,因为会话本身会在服务端留下一些信息。
会话可以使用的HTTP访问方法支持大部分的HTTP谓词,其使用格式如下:
sesison.get('url')
session.post('url', data=b'data')
session.put('url', data=b'data')
sesison.delete('url')
sesison.head('url')
sesison.options('url')
session.patch('url', data=b'data')
解析响应内容
会话访问指定URL返回的ClientResponse
类型的结果中携带了全部服务器的响应内容。其中使用gzip和deflate压缩传输的内容将会被自动解压缩。
通常可以使用response.text()
这个异步方法来获取响应的主体内容。response.status
属性可以用来获取服务器响应的HTTP状态码。如果要获取二进制响应体内容,可以使用response.read()
这个异步方法。此外还可以直接使用response.json()
异步方法来获取JSON格式的响应体并直接进行解析。
如果响应体内容很长,可以直接使用response.content
属性来进行响应流的操作。
传递Query参数
HTTP谓词一般都可以携带Query参数。aiohttp在进行HTTP访问时,不需要将Query参数手工拼入URL中,只需要将Query参数内容传入谓词方法的params
参数中。
params
参数接受字典({'key': 'value'}
)、元组列表[('key', 'value')]
等类型的内容。
具体使用可参考以下示例:
params = {'key1': 'value1', 'key2': 'value2'}
async with session.get('http://www.baidu.com/', params=params) as r:
assert str(r.url) == 'http://www.baidu.com/?key1=value1&key2=value2'
传递JSON参数
在使用POST等方法时,可以使用data
参数来上传字典类型的表单数据。但是在目前的项目开发中,使用JSON格式的表单数据会变得更加常见。
aiohttp也支持使用JSON格式的表单数据,只需要使用字典类型的数据传递给json
参数而不是data
参数即可,例如:session.post(url, json={'key': 'value'})
。
上传文件
上传文件也是HTTP访问中经常要做的操作之一,aiohttp中上传文件非常简单。以下是一个上传文件的示例。
files = {'file': open(path, 'rb')}
await session.post(url, data=files)
或者还可以使用FormData()
方法来对表单数据进行精细化配置。除此之外,可以使用流来上传文件,以下给出一个使用流上传文件的最简单示例。
with open(path, 'rb') as f:
await session.post(url, data=f)
或者还可以使用异步生成器来传输更大的文件。
async def file_sender(file_name=None):
async with asiofiles.open(file_name, 'rb') as f:
chunk = await f.read(64*1024)
while chunk:
yield chunk
chunk = await f.read(64*1024)
async with session.post(url, data=file_sender(path)) as resp:
print(await resp.text())
Websocket访问
aiohttp功能库内置了WebSocket的支持,使用会话连接WebSocket会得到一个ClientWebSocketResponse
类型实例,用来进行实时通讯。可以仿照下例来书写WebSocket访问。
async with session.ws_connect(ws_url) as ws:
async for msg in ws:
if msg.type == aiohttp.WSMsgType.TEXT:
if msg.data == 'close cmd':
await ws.close
break;
else:
await ws.send_str(msg.data + '/answer')
elif msg.type == aiohttp.WSMsgType.ERROR:
break
WebSocket在同一时刻只能有一个读取任务,但是可以有多个写入任务。
头信息
头信息是HTTP请求中重要的信息储存位置,所有HTTP谓词访问方法都支持使用headers
参数接受一个字典来对HTTP请求的头信息进行设置。
此外,跟随头信息设定的还有Cookies信息,这是使用coookies
参数来设定的,Cookies参数同样接受一个字典类型的对象。
对于服务器响应信息中的头信息和Cookies信息的访问,可以分别通过headers
和cookies
属性来访问,这两个属性中保存的信息都是字典类型,可以直接使用键值来访问。
连接池
默认情况下,aiohttp会同时并发进行全部的HTTP请求(默认上限为100个请求)。但是很多情况下需要对同时连接数进行限制,这时就可以使用连接池技术。aiohttp功能库提供了TCPConnector()
方法,允许用户对HTTP连接进行细致的调控,连接池就是使用TCPConnector类来完成的配置。
conn = aiohttp.TCPConnector(limit=10) # 限制全局并发连接数为10个
conn = aiohttp.TCPConnector(limit_per_host=20) # 限制每个host的并发连接数为20个
session = aiohttp.ClientSession(connector=conn) # 使用TCPConnector初始化会话。