Aiohttp官方文档翻译-客户端

快速开始

Request

不要为每个请求创建会话。每个应用程序很可能需要一个会话来执行所有请求。

更复杂的情况可能需要每个站点进行一次会话,例如一个用于Github,另一个用于Facebook API。无论如何,为每个请求建立会话是一个非常糟糕的主意。

会话内部包含一个连接池。连接重用和保持活动状态(默认情况下均处于启用状态)可能会提高整体性能。

简单请求

import aiohttp

async with aiohttp.ClientSession() as session:
    async with session.get('http://httpbin.org/get') as resp:
        print(resp.status)
        print(await resp.text())

其他请求方法

session.post('http://httpbin.org/post', data=b'data')
session.put('http://httpbin.org/put', data=b'data')
session.delete('http://httpbin.org/delete')
session.head('http://httpbin.org/get')
session.options('http://httpbin.org/get')
session.patch('http://httpbin.org/patch', data=b'data')

非上下文

session = aiohttp.ClientSession()
async with session.get('...'):
    # ...
await session.close()

传递参数

dict

params = {'key1': 'value1', 'key2': 'value2'}
async with session.get('http://httpbin.org/get',
                       params=params) as resp:
    expect = 'http://httpbin.org/get?key2=value2&key1=value1'
    assert str(resp.url) == expect

list

params = [('key', 'value1'), ('key', 'value2')]
async with session.get('http://httpbin.org/get',
                       params=params) as r:
    expect = 'http://httpbin.org/get?key=value2&key=value1'
    assert str(r.url) == expect

string

# 注意内容不是由库编码的。示例中+未被编码:
async with session.get('http://httpbin.org/get',
                       params='key=value+1') as r:
        assert str(r.url) == 'http://httpbin.org/get?key=value+1'

注意

aiohttp在发送请求之前在内部执行URL规范化。

规范化通过IDNA编解码器对主机部分进行编码,并将重引用应用于路径和查询部分。

例如,URL(http://example.com/путь/%30?a=%31)转换为URL(http://example.com/%D0%BF%D1%83%D1%82%D1%8C/0?a=1)。

如果服务器接受精确的表示并且不重新引用URL本身,则有时不希望进行规范化。

要禁用规范化,请使用`encode = True`参数进行URL构建

await session.get(
    URL('http://example.com/%30', encoded=True)
)

复杂POST

  • form-encoded

表单形式,字典形式

payload = {'key1': 'value1', 'key2': 'value2'}
async with session.post('http://httpbin.org/post',
                        data=payload) as resp:
    print(await resp.text())
  • application/octet-stream

非表单形式,byte形式

async with session.post(url, data=b'\x00Binary-data\x00') as resp:
    ...
  • json
async with session.post(url, json={'example': 'test'}) as resp:
    ...

默认使用标准json模块序列化,也可指定序列化器

import ujson

async with aiohttp.ClientSession(
        json_serialize=ujson.dumps) as session:
    await session.post(url, json={'test': 'object'})
  • text
async with session.post(url, data='Тест') as resp:
    ...
  • Multipart-encoded
url = 'http://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}

await session.post(url, data=files)

设置文件名和内容类型

url = 'http://httpbin.org/post'
data = FormData()
data.add_field('file',
               open('report.xls', 'rb'),
               filename='report.xls',
               content_type='application/vnd.ms-excel')

await session.post(url, data=data)
  • streaming

aiohttp支持多种类型的流上传,这使您可以发送大文件而无需将其读入内存。

文件对象

with open('massive-body', 'rb') as f:
   await session.post('http://httpbin.org/post', data=f)

异步生成器

async def file_sender(file_name=None):
    async with aiofiles.open(file_name, 'rb') as f:
        chunk = await f.read(64*1024)
        while chunk:
            yield chunk
            chunk = await f.read(64*1024)

# Then you can use file_sender as a data provider:

async with session.post('http://httpbin.org/post',
                        data=file_sender(file_name='huge_file')) as resp:
    print(await resp.text())

因为content属性是StreamReader(提供了异步迭代器协议),可以将获取和发布请求链接在一起:

resp = await session.get('http://python.org')
await session.post('http://httpbin.org/post',
                   data=resp.content)

Response

简单响应

async with session.get('https://api.github.com/events') as resp:
    print(resp.status)
    print(await resp.text())

# 200
# '[{"created_at":"2015-06-12T14:06:22Z","public":true,"actor":{...

aiohttp自动解码服务器中的内容。也可指定自定义编码

await resp.text(encoding='windows-1251')

二进制

print(await resp.read())

# b'[{"created_at":"2015-06-12T14:06:22Z","public":true,"actor":{...

gzipdeflate传输编码会自动为您解码。

可以启用brotli传输编码支持,只需安装brotlipy.。

JSON

使用默认的json解码器,也可以为json()调用指定自定义编码和解码器功能。

async with session.get('https://api.github.com/events') as resp:
    print(await resp.json())

Stream

尽管read()json()text()方法非常方便,但您应谨慎使用它们。所有这些方法将整个响应加载到内存中。可以使用content属性。它是aiohttp.StreamReader类的实例。

gzipdeflate传输编码会自动解码

从内容中显式读取之后,不能使用read(),json(),text()

async with session.get('https://api.github.com/events') as resp:
    await resp.content.read(10)

但是,一般而言,您应该使用以下模式来保存流式传输到文件中的内容

with open(filename, 'wb') as fd:
    while True:
        chunk = await resp.content.read(chunk_size)
        if not chunk:
            break
        fd.write(chunk)

超时

超时设置存储在ClientTimeout数据结构中。

默认情况下,aiohttp总共使用5分钟的超时时间,这意味着整个操作应在5分钟内完成。

session中覆盖

timeout = aiohttp.ClientTimeout(total=60)
async with aiohttp.ClientSession(timeout=timeout) as session:
    ...

request中覆盖

async with session.get(url, timeout=timeout) as resp:
    ...

默认形式

aiohttp.ClientTimeout(total=5*60, connect=None,
                      sock_connect=None, sock_read=None)

WebSockets

内置了websocket服务

ws = aiohttp.ClientSession.ws_connect()  # 连接ws服务器
await ws.receive()  # 获取回复信息
await ws.sen_str('data')  # 发送信息

示例

async with session.ws_connect('http://example.org/ws') as ws:
    async for msg in ws:  # await ws.receive()
        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
posted @ 2020-08-18 13:09  fhkankan  阅读(366)  评论(0编辑  收藏  举报