---
title: ByteStream
description: "One side of a spawned exec's output, as an iterator of bytes."
---

```python
@final
class ByteStream
```

One side of a spawned exec's output, as an iterator of `bytes`.

Ends with `StopIteration` after the command's `exit`, and raises the error that ended the
side otherwise: a gap under the default policy, or a failure the stream couldn't reconnect
through. The `receiver` is behind a `Mutex` for the reason `ExecStream`'s is: `recv` needs
`&mut`, and the lock is held only across one `recv`, never across a Python callback.

## Constructor

`ByteStream` declares no `__new__` or `__init__`, so it is not constructed directly: an instance comes back from another call in this package.

## Special methods

### `__aiter__`

```python
def __aiter__() -> ByteStream
```

### `__anext__`

```python
def __anext__() -> Awaitable[bytes]
```

The next chunk, awaited, or `StopAsyncIteration` when the side ends: `async for`.
Cancelling the await leaves the chunk unread, as `ExecStream.__anext__` does.

### `__iter__`

```python
def __iter__() -> ByteStream
```

### `__next__`

```python
def __next__() -> bytes
```

The next chunk, or `StopIteration` when the side ends.

Blocks with the GIL released, so another Python thread (the one reading the other side)
runs while this one waits on the daemon. The end is raised rather than returned as
`None`, as `ExecStream`'s is, so the stub's element type is `bytes` and not
`bytes | None`.

## Provenance

This page is generated from `bindings/microvms-py/microvms.pyi` by Griffe 2.3.0, run from `site/scripts/gen-reference.mjs` on every `pnpm run sync`, so an edit made here is overwritten by the next run.

To change the page, change the doc comment in the binding's Rust source, then regenerate the declarations with `mise run stubs`. `mise run stubs:check` fails when the committed file no longer matches the source.