Python httpx模块的介绍
HTTP协议是客户端和服务端之间通信的核心协议,对于处理API、爬虫等任务特别重要。Python自带多个HTTP请求库,如requests、urllib等,然而,它们的性能不太高。
为了解决这些问题,来自编写 requests-mock 的 Tom Christie 在同样的语法基础之上编写了 httpx,您可以把它看作是更好的 requests。
httpx 统一了同步、异步请求和WebSocket客户端,为Python开发者带来了新的体验。
httpx的安装和快速入门
推荐使用pip安装:
$ pip install httpx
安装之后,让我们做一些快速实验看看吧!
首先,打开 Python/Edit,输入以下代码:
import httpx
r = httpx.get('https://www.google.com/')
print(r.text)
然后运行它,我们会得到Google首页上的HTML代码。
现在我们来做POST请求:
import httpx
data = {"username": "zhugexu", "passwor_d": "123456"}
r = httpx.post('http://httpbin.org/post', data=data)
print(r.text)
在这里,我们在httpbin.org网站上进行了一个POST请求,我们可以看到输出的结果中包含了我们刚刚POST的数据。
发送文件和Json数据
发送文件和Json是常规的HTTP操作之一,现在让我们来研究如何使用 httpx 执行这些请求。
发送文件
有时我们需要通过表单上传文件,httpx 也支持这种操作。可以使用httpx.post()
发送multipart/form-data:
import httpx
url = 'https://httpbin.org/post'
with open('./cute_cat.jpg', 'rb') as f:
files = {'upload_file': f}
data = {'username': 'zhugexu'}
r = httpx.post(url, files=files, data=data)
print(r.text)
它将会在The HTML file input element的描述中返回你上传的文件名、文件类型和文件内容。
发送Json数据
发送Json数据只需要将参数变成一个字典对象,然后指定Content-Type为application/json即可。
假设我们有一个Json格式的数据,内容如下:
{
"name": "zhugexu",
"age": 25,
}
尝试用httpx发一个post请求:
import httpx
data = {"name": "zhugexu", "age": 25}
headers = {"Content-Type": "application/json"}
r = httpx.post('http://httpbin.org/post', json=data, headers=headers)
print(r.json())
同步和异步请求
httpx 提供了两种方式来处理异步请求:async/await和asyncio。
而同步请求就是传统的请求方式,可以查看上面的示例代码(示例都是同步请求)。
异步请求
我们可以用httpx.AsyncClient()
代替httpx.Client()
来进行异步请求。
import asyncio
import httpx
async def fetch(client):
resp = await client.get('http://example.org')
return resp.text
async def main():
async with httpx.AsyncClient() as client:
html = await fetch(client)
print(html)
if __name__ == "__main__":
asyncio.run(main())
在上面的示例代码中,我们使用了async/await关键字来使整个流程变为协程的形式。
Async/await
协程是 Python3.5 以后引入的概念,它可以在一定程度上模拟多线程的功能,但是实现方式更加简单、更容易掌握。
一个协程的定义界定于一个异步执行器中,这个异步执行器可以使用三个不同的方法之一来创建:async、asyncio、trio或 curio。
async and await
async / await 是 Python3.5 引入协程的新语言构造。
async 用于声明异步执行的函数或上下文
await 用于调用异步执行的对象
asyncio异步
import httpx
import asyncio
async def main():
async with httpx.AsyncClient() as client:
r = await client.get('https://www.baidu.com')
print(r.text)
if __name__ == '__main__':
asyncio.run(main())
在上面的示例代码中,我们首先定义了一个异步函数main()。在函数中,我们创建了一个异步客户端对象httpx.AsyncClient()。
WebSocket客户端
支持WebSocket的HTTP客户端是 API 开发中的常见需求,不过常规的HTTP库通常都不支持 WebSocket,它们在处理 Websockets 时比较麻烦。但是,httpx 做到了。
WebSocket在Python中的非标准库实现很多,httpx中,我们可以使用asyncio实现一个WebSocket服务器,这样就可以在Python中使用WebSocket技术,方便快捷。
import asyncio
import httpx
from httpx_socks import AsyncProxyTransport
class Client:
def __init__(self):
self.open = False
self.client = httpx.AsyncClient(transports=[AsyncProxyTransport.from_url('socks5://localhost:1080')])
async def connect(self):
websocket_uri = "ws://echo.websocket.org"
self.websocket = await self.client.websocket_connect(websocket_uri)
self.open = True
async def receive(self):
return await self.websocket.receive()
async def send(self, message):
await self.websocket.send_text(message)
async def close(self):
self.open = False
await self.websocket.close()
async def main():
client = Client()
await client.connect()
if __name__ == '__main__':
asyncio.run(main())
在上面的代码中,我们成功地通过 httpx 库,使用了 WebSocket 服务,传输了一条信息。我们调用了 httpx.AsyncClient.websocket_connect()
方法,它返回的是 httpx.WebSocketResponse
类的实例。
结语
httpx 整合了 Python 现有得异步编程模型的优势,提供了与同步 API 请求相比性能更高的接口方法。从语用、功能和性能的多个角度来看,它的确是一个相当不错的库。