开放的编程资料库

当前位置:我爱分享网 > Python教程 > 正文

Python使用httpx

Pythonhttpx教程展示了如何使用httpx模块在Python中创建HTTP请求。httpx允许创建同步和异步HTTP请求。

httpx模块

HTTPX是Python3的HTTP客户端,它提供同步和异步API,并支持HTTP/1.1和HTTP/2。它具有与流行的Python请求库类似的API。HTTPX需要Python3.6+。

$ pip install httpx

我们使用pip命令安装模块。

httpx支持异步网络请求。通过结合使用httpx和asyncio模块以及async和await关键字,我们可以生成异步Web请求。这可能会大大提高我们程序的效率。

HTTP

超文本传输​​协议(HTTP)是分布式协作超媒体信息系统的应用协议。HTTP是万维网数据通信的基础。

Pythonhttpx状态码

在第一个示例中,我们确定网页的状态。状态代码由status_code属性确定。

#!/usr/bin/python

import httpx 

r = httpx.head('http://webcode.me')
print(r.status_code)

该示例创建对webcode.me网站的同步HEAD请求并检索http响应。从响应中,我们得到状态码。

$ ./sync_status.py 
200

PythonhttpxGET请求

以下示例创建同步GET请求。

#!/usr/bin/python

import httpx 

r = httpx.get('http://webcode.me')
print(r.text)

我们使用httpx.get方法生成对网页的GET请求。检索页面并将其HTML代码打印到控制台。

$ ./sync_get.py 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My html page</title>
</head>
<body>

    <p>
        Today is a beautiful day. We go swimming and fishing.
    </p>
    
    <p>
         Hello there. How are you?
    </p>
    
</body>
</html>

有一个params选项可以随请求发送查询参数。

#!/usr/bin/python

import httpx 

payload = {'name': 'John Doe', 'occupation': 'gardener'}
r = httpx.get('https://httpbin.org/get', params = payload)
print(r.text)

该示例使用GET请求发送查询参数。

$ ./sync_query_params.py 
{
    "args": {
    "name": "John Doe", 
    "occupation": "gardener"
    }, 
    "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate, br", 
    "Host": "httpbin.org", 
    "User-Agent": "python-httpx/0.16.1", 
    "X-Amzn-Trace-Id": "Root=1-600817ec-25cb3dea461b3e7a6f21df27"
    }, 
    ...
    "url": "https://httpbin.org/get?name=John+Doe&occupation=gardener"
}

PythonhttpxPOST表单请求

POST请求是用httpx.post方法生成的。

使用application/x-www-form-urlencoded,数据在请求正文中发送;键和值被编码在由“&”分隔的键值元组中,键和值之间有一个“=”。

#!/usr/bin/python

import httpx 

payload = {'name': 'John Doe', 'occupation': 'gardener'}

r = httpx.post('https://httpbin.org/post', data=payload)
print(r.text)

我们生成一个带有FORM数据的同步POST请求到httpbin.org/post。有效负载设置为data选项。

$ ./sync_post_form.py 
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "name": "John Doe", 
    "occupation": "gardener"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate, br", 
    "Content-Length": "33", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "python-httpx/0.16.1", 
    "X-Amzn-Trace-Id": "Root=1-600819fd-5e7b28a97b2484c8438a6f2e"
  }, 
  "json": null, 
  ... 
  "url": "https://httpbin.org/post"
}

Pythonhttpx流数据

对于较大的下载,我们可以流式传输不会立即将整个响应主体加载到内存中的响应。对于流式传输,我们使用httpx.stream方法。

#!/usr/bin/python

import httpx

url = 'https://download.freebsd.org/ftp/releases/amd64/amd64/ISO-IMAGES/12.0/FreeBSD-12.0-RELEASE-amd64-mini-memstick.img'

with open('FreeBSD-12.0-RELEASE-amd64-mini-memstick.img', 'wb') as f:

    with httpx.stream('GET', url) as r:

        for chunk in r.iter_bytes():
            f.write(chunk)

该示例下载FreeBSD操作系统的映像。我们使用iter_bytes方法遍历二进制内容。

Pythonhttpx异步GET请求

以下示例生成一个简单的异步GET请求。

#!/usr/bin/python

import httpx
import asyncio

async def main():
    async with httpx.AsyncClient() as client:
        r = await client.get('http://test.webcode.me')
        print(r.text)

asyncio.run(main())

在示例中,我们异步检索一个小的HTML页面。

import httpx
import asyncio

我们需要导入httpxasyncio模块。asyncio模块是一个使用async/await语法编写并发代码的库;它通常非常适合IO密集型任务。

async def main():

使用asyncdef,我们创建了一个协程。协程用于协作式多任务处理。

async with httpx.AsyncClient() as client:

我们创建一个异步HTTP客户端。该库还必须支持异步编程模型。

r = await client.get('http://test.webcode.me')

使用await关键字,启动get协程,然后程序恢复执行;协程将执行的控制权交还给事件循环。所以程序不会停止等待请求。当请求到达时,事件循环在等待协程的地方继续。

asyncio.run(main())

run方法启动事件循环并调用main协程。事件循环是注册、执行和取消异步函数的中心点。

Pythonhttpx多个异步GET请求

asyncio.gather函数并发运行协程。

#!/usr/bin/python

import httpx
import asyncio

async def get_async(url):
    async with httpx.AsyncClient() as client:
        return await client.get(url)

urls = ["http://webcode.me", "https://httpbin.org/get"]

async def launch():
    resps = await asyncio.gather(*map(get_async, urls))
    data = [resp.text for resp in resps]
    
    for html in data:
        print(html)

asyncio.run(launch())

该示例生成两个异步GET请求。

async def get_async(url):
     async with httpx.AsyncClient() as client:
         return await client.get(url)

这是生成异步GET请求的协程。

urls = ["http://webcode.me", "https://httpbin.org/get"]

我们有两个URL。

async def launch():
     resps = await asyncio.gather(*map(get_async, urls))
     data = [resp.text for resp in resps]
     
     for html in data:
         print(html)

通过内置的map函数,我们将get_async函数应用于URL列表。使用*(星号)运算符将返回的列表解压缩为位置参数。如果所有协程都成功完成,则结果是返回值(HTML代码)的聚合列表。

Pythonhttpx异步POST表单请求

以下示例显示了如何发送带有表单数据的异步POST请求。

#!/usr/bin/python

import httpx
import asyncio

async def main():

    data = {'name': 'John Doe', 'occupation': 'gardener'}

    async with httpx.AsyncClient() as client:
        r = await client.post('https://httpbin.org/post', data=data)
        print(r.text)

asyncio.run(main())

数据被传递给post协程的data选项。

Pythonhttpx异步POSTJSON请求

以下示例展示了如何使用JSON数据发送异步POST请求。

#!/usr/bin/python

import httpx
import asyncio

async def main():

    data = {'int': 123, 'boolean': True, 'list': ['a', 'b', 'c']}

    async with httpx.AsyncClient() as client:
        r = await client.post('https://httpbin.org/post', json=data)
        print(r.text)

asyncio.run(main())

数据设置为post协程的json选项。

Pythonhttpx异步流请求

该示例展示了如何在异步流中下载大型二进制文件。

#!/usr/bin/python

import httpx
import asyncio

url = 'https://download.freebsd.org/ftp/releases/amd64/amd64/ISO-IMAGES/12.0/FreeBSD-12.0-RELEASE-amd64-mini-memstick.img'


async def main():
    with open('FreeBSD-12.0-RELEASE-amd64-mini-memstick.img', 'wb') as f:

        async with httpx.AsyncClient() as client:
            async with client.stream('GET', url) as r:

                async for chunk in r.aiter_bytes():
                    f.write(chunk)

asyncio.run(main())

我们使用client.streamaiter_bytes函数。

比较同步和异步请求

在下面两个例子中,我们比较了一组同步和异步请求的效率。使用time模块,我们计算经过的时间。

#!/usr/bin/python

import httpx
import time

urls = ['http://webcode.me', 'https://httpbin.org/get', 
    'https://google.com', 'https://stackoverflow.com', 
    'https://github.com', 'https://mozilla.org']

start_time = time.monotonic()

for url in urls:
    r = httpx.get(url)
    print(r.status_code)

print(f'Elapsed: {time.monotonic() - start_time}')

我们生成六个同步GET请求并计算经过的时间。

#!/usr/bin/python

import httpx
import asyncio
import time

async def get_async(url):
    async with httpx.AsyncClient() as client:
        return await client.get(url)

urls = ['http://webcode.me', 'https://httpbin.org/get', 
    'https://google.com', 'https://stackoverflow.com', 
    'https://github.com']

async def launch():
    resps = await asyncio.gather(*map(get_async, urls))
    data = [resp.status_code for resp in resps]
    
    for status_code in data:
        print(status_code)

start_time = time.monotonic()
asyncio.run(launch())
print(f'Elapsed: {time.monotonic() - start_time}')

我们生成六个异步GET请求。

$ ./multiple_async.py 
200
200
200
200
200
Elapsed: 0.935432159982156
$ ./multiple_sync.py 
200
200
200
200
200
200
Elapsed: 3.5428215700085275

在我们的案例中,差异超过2.5秒。

在本教程中,我们使用httpx模块在Python中生成了同步和异步Web请求。

列出所有Python教程。

未经允许不得转载:我爱分享网 » Python使用httpx

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏