Skip to content

异步支持

¥Async Support

HTTPX 默认提供标准同步 API,但如果您需要,也可以提供异步客户端选项。

¥HTTPX offers a standard synchronous API by default, but also gives you the option of an async client if you need it.

Async 是一种比多线程效率高得多的并发模型,可以提供显著的性能优势并支持使用 WebSocket 等长寿命网络连接。

¥Async is a concurrency model that is far more efficient than multi-threading, and can provide significant performance benefits and enable the use of long-lived network connections such as WebSockets.

如果您正在使用异步 Web 框架,那么您还需要使用异步客户端来发送传出的 HTTP 请求。

¥If you're working with an async web framework then you'll also want to use an async client for sending outgoing HTTP requests.

发出异步请求

¥Making Async requests

要发出异步请求,您需要一个AsyncClient

¥To make asynchronous requests, you'll need an AsyncClient.

>>> async with httpx.AsyncClient() as client:
...     r = await client.get('https://www.example.com/')
...
>>> r
<Response [200 OK]>

提示

¥Tip

使用IPython或 Python 3.9+python -m asyncio以交互方式尝试此代码,因为它们支持执行async/await控制台中的表达式。

¥Use IPython or Python 3.9+ with python -m asyncio to try this code interactively, as they support executing async/await expressions in the console.

API 差异

¥API Differences

如果您使用异步客户端,那么有一些使用异步方法的 API。

¥If you're using an async client then there are a few bits of API that use async methods.

发出请求

¥Making requests

请求方法都是异步的,所以你应该使用response = await client.get(...)以下所有内容的样式:

¥The request methods are all async, so you should use response = await client.get(...) style for all of the following:

  • AsyncClient.get(url, ...)

    ¥AsyncClient.get(url, ...)

  • AsyncClient.options(url, ...)

    ¥AsyncClient.options(url, ...)

  • AsyncClient.head(url, ...)

    ¥AsyncClient.head(url, ...)

  • AsyncClient.post(url, ...)

    ¥AsyncClient.post(url, ...)

  • AsyncClient.put(url, ...)

    ¥AsyncClient.put(url, ...)

  • AsyncClient.patch(url, ...)

    ¥AsyncClient.patch(url, ...)

  • AsyncClient.delete(url, ...)

    ¥AsyncClient.delete(url, ...)

  • AsyncClient.request(method, url, ...)

    ¥AsyncClient.request(method, url, ...)

  • AsyncClient.send(request, ...)

    ¥AsyncClient.send(request, ...)

打开和关闭客户端

¥Opening and closing clients

使用async with httpx.AsyncClient()如果您想要一个上下文管理的客户端...

¥Use async with httpx.AsyncClient() if you want a context-managed client...

async with httpx.AsyncClient() as client:
    ...

警告

¥Warning

为了从连接池中获得最大收益,请确保您没有实例化多个客户端实例 - 例如通过使用async with在“热循环”中。这可以通过拥有一个单一作用域的客户端来实现,该客户端会在需要的地方传递,或者通过拥有一个单一的全局客户端实例来实现。

¥In order to get the most benefit from connection pooling, make sure you're not instantiating multiple client instances - for example by using async with inside a "hot loop". This can be achieved either by having a single scoped client that's passed throughout wherever it's needed, or by having a single global client instance.

或者,使用await client.aclose()如果你想明确关闭客户端:

¥Alternatively, use await client.aclose() if you want to close a client explicitly:

client = httpx.AsyncClient()
...
await client.aclose()

流式响应

¥Streaming responses

AsyncClient.stream(method, url, ...)方法是一个异步上下文块。

¥The AsyncClient.stream(method, url, ...) method is an async context block.

>>> client = httpx.AsyncClient()
>>> async with client.stream('GET', 'https://www.example.com/') as response:
...     async for chunk in response.aiter_bytes():
...         ...

异步响应流方法包括:

¥The async response streaming methods are:

  • Response.aread()- 用于有条件地读取流块内的响应。

    ¥Response.aread() - For conditionally reading a response inside a stream block.

  • Response.aiter_bytes()- 将响应内容以字节形式流式传输。

    ¥Response.aiter_bytes() - For streaming the response content as bytes.

  • Response.aiter_text()- 将响应内容以文本形式流式传输。

    ¥Response.aiter_text() - For streaming the response content as text.

  • Response.aiter_lines()- 将响应内容以文本行的形式流式传输。

    ¥Response.aiter_lines() - For streaming the response content as lines of text.

  • Response.aiter_raw()- 用于流式传输原始响应字节,而不应用内容解码。

    ¥Response.aiter_raw() - For streaming the raw response bytes, without applying content decoding.

  • Response.aclose()- 用于关闭响应。通常不需要这样做,因为.stream块在退出时自动关闭响应。

    ¥Response.aclose() - For closing the response. You don't usually need this, since .stream block closes the response automatically on exit.

对于上下文块使用不实际的情况,可以通过发送Request实例使用client.send(..., stream=True)

¥For situations when context block usage is not practical, it is possible to enter "manual mode" by sending a Request instance using client.send(..., stream=True).

将响应转发到流式 Web 端点的示例星光

¥Example in the context of forwarding the response to a streaming web endpoint with Starlette:

import httpx
from starlette.background import BackgroundTask
from starlette.responses import StreamingResponse

client = httpx.AsyncClient()

async def home(request):
    req = client.build_request("GET", "https://www.example.com/")
    r = await client.send(req, stream=True)
    return StreamingResponse(r.aiter_text(), background=BackgroundTask(r.aclose))

警告

¥Warning

使用此“手动流模式”时,作为开发人员,您有责任确保Response.aclose()最终会被调用。如果不这样做,连接就会保持打开状态,很可能会导致资源泄漏。

¥When using this "manual streaming mode", it is your duty as a developer to make sure that Response.aclose() is called eventually. Failing to do so would leave connections open, most likely resulting in resource leaks down the line.

流式请求

¥Streaming requests

当发送带有AsyncClient例如,您应该使用异步字节生成器而不是字节生成器:

¥When sending a streaming request body with an AsyncClient instance, you should use an async bytes generator instead of a bytes generator:

async def upload_bytes():
    ...  # yield byte content

await client.post(url, content=upload_bytes())

显式传输实例

¥Explicit transport instances

直接实例化传输实例时,需要使用httpx.AsyncHTTPTransport

¥When instantiating a transport instance directly, you need to use httpx.AsyncHTTPTransport.

例如:

¥For instance:

>>> import httpx
>>> transport = httpx.AsyncHTTPTransport(retries=1)
>>> async with httpx.AsyncClient(transport=transport) as client:
>>>     ...

支持的异步环境

¥Supported async environments

HTTPX 支持asyncio或者trio作为异步环境。

¥HTTPX supports either asyncio or trio as an async environment.

它将自动检测使用哪一个作为套接字操作和并发原语的后端。

¥It will auto-detect which of those two to use as the backend for socket operations and concurrency primitives.

异步IO

¥AsyncIO

AsyncIO 是 Python 的内置库使用 async/await 语法编写并发代码。

¥AsyncIO is Python's built-in library for writing concurrent code with the async/await syntax.

import asyncio
import httpx

async def main():
    async with httpx.AsyncClient() as client:
        response = await client.get('https://www.example.com/')
        print(response)

asyncio.run(main())

三重奏

¥Trio

Trio 是另一个异步库,围绕结构化并发原则

¥Trio is an alternative async library, designed around the the principles of structured concurrency.

import httpx
import trio

async def main():
    async with httpx.AsyncClient() as client:
        response = await client.get('https://www.example.com/')
        print(response)

trio.run(main)

重要的

¥Important

trio必须安装包才能使用 Trio 后端。

¥The trio package must be installed to use the Trio backend.

AnyIO

¥AnyIO

AnyIO 是一个异步网络和并发库可以在以下任一基础上运行asyncio或者trio。它与您选择的后端的本机库融合(默认为asyncio)。

¥AnyIO is an asynchronous networking and concurrency library that works on top of either asyncio or trio. It blends in with native libraries of your chosen backend (defaults to asyncio).

import httpx
import anyio

async def main():
    async with httpx.AsyncClient() as client:
        response = await client.get('https://www.example.com/')
        print(response)

anyio.run(main, backend='trio')

调用 Python Web 应用

¥Calling into Python Web Apps

有关直接调用 ASGI 应用程序的详细信息,请参阅ASGITransport文档

¥For details on calling directly into ASGI applications, see the ASGITransport docs.