Skip to main content
Version: 3.3

StreamedRequestBody

A request body sent from its source in chunks, so the body is never held in memory whole.

HttpClient.call and HttpClientAsync.call wrap a data argument that is a file-like object, an iterable of byte chunks, or a streamed HttpResponse in this class. The transport pulls the chunks from iter_bytes or aiter_bytes and sends each one as it arrives, and the body is never compressed. Build one yourself and pass it as the data to choose the chunk_size, and it is sent as it is.

An io.IOBase stream, such as an open file or an io.BytesIO, is read in chunk_size pieces. Any other object with a callable read is read whole with a single read() call and sent as one chunk, since nothing else about its shape is known.

The shared retry loop can send a body again only when its source is a seekable io.IOBase stream, in which case rewind seeks back to where the source was when the body was created. Any other source is consumed by the attempt that sends it, so the request gets a single attempt.

A file opened in text mode, or an iterable yielding strings, is UTF-8 encoded chunk by chunk. A file-like object whose read is a coroutine function, as aiofiles provides, and an async iterable can only be sent by the asynchronous client.

Warning

This is an experimental feature. The behavior and interface may change in future versions.

Index

Async Resource Clients

is_async

is_async: bool

Whether the chunks can only be produced asynchronously, so only HttpClientAsync can send the body.

Methods

__init__

  • __init__(source, *, chunk_size): None
  • Initialize the streamed request body.


    Parameters

    • source: StreamedBodySource

      The object the chunks come from. See is_streamable for the accepted kinds.

    • optionalkeyword-onlychunk_size: int = STREAMED_BODY_CHUNK_SIZE

      Size of the chunks an io.IOBase source is read in - bytes from a binary stream, characters from a text-mode one. Any other source decides its own chunk sizes.

    Returns None

aclose_chunks

  • async aclose_chunks(): None
  • Close the chunks the last aiter_bytes call handed out, and with them a generator or async generator source.

    The asynchronous counterpart of close_chunks.


    Returns None

aiter_bytes

  • aiter_bytes(): AsyncGenerator[bytes]
  • Yield the body in chunks asynchronously, pulling a synchronous source in a worker thread.

    A blocking read or __next__ would stall the event loop, so a synchronous file-like object or iterator is pulled through asyncio.to_thread, one chunk at a time. Closing the returned generator, directly or through aclose_chunks, also closes a generator or async generator source.


    Returns AsyncGenerator[bytes]

close_chunks

  • close_chunks(): None
  • Close the chunks the last iter_bytes call handed out, and with them a generator source.

    The retry loop calls this once an attempt ends. A transport may stop pulling the chunks early, for example on an error response sent before the whole body arrived, and hold on to them for as long as its client lives, which keeps the source suspended. When the transport is still pulling a chunk in a worker thread, a generator source is closed and a file-like source is read no further as soon as that chunk arrives.


    Returns None

is_streamable

  • Return whether a request body can be streamed from a value.

    These are, checked in this order, a streamed HttpResponse (anything with a callable iter_bytes), an io.IOBase stream, any other file-like object (anything with a callable read), and an iterable or async iterable of byte chunks: an iterator such as a generator, or an object that only implements __iter__ or __aiter__, which is what a class yielding chunks from a generator method looks like. A str, bytes, bytearray, a container such as a list, tuple, set, or dict, and a pydantic model are not sources, even though all of them can be iterated. They are the values the client uploads whole or serializes as JSON.

    A StreamedRequestBody matches on its own iter_bytes, which is how a hand-built body reaches the request pipeline untouched. The constructor refuses one, so a caller that builds a body from what this accepts has to check for an existing body first.


    Parameters

    • value: object

    Returns TypeGuard[StreamedBodySource]

iter_bytes

  • iter_bytes(): Generator[bytes]
  • Yield the body in chunks, reading an io.IOBase source in chunk_size pieces.

    Closing the returned generator, directly or through close_chunks, also closes a generator source.


    Returns Generator[bytes]

rewind

  • rewind(): None
  • Seek the source back to where it was when the body was created, so the body can be sent again.


    Returns None

Properties

error

error: Exception | None

The exception the source raised while the chunks were pulled, if any.

A transport reports such a failure as its own error, which may wrap the cause beyond recognition. The retry loop raises this exception instead, since sending the body again cannot fix its source.

rewindable

rewindable: bool

Whether the body can be sent again after rewind, which only a seekable io.IOBase source allows.