Skip to main content

LiveZip

Memory-bound, streamable ZIP64 archives — from any source.

LiveZip builds a ZIP file as an iterator of byte chunks. It never holds the archive and never holds a payload: at any moment it keeps only a small descriptor per file, regardless of how large the files are. Where the bytes come from — disk, HTTP, memory, an S3 bucket — is a detail, and sources can be mixed in one archive.

  • Predictable size — the exact archive size is known before a single payload byte is read, so it can be announced as Content-Length.
  • Bounded memory — O(k) in the number of files, O(n) in time; size the machine by file count, not by total weight.
  • Any source, mixed — local files, HTTP URLs, in-memory buffers and S3 objects, all through the same encoder.

CI Docs Python License

Documentation

Full documentation: https://offworldnexus.github.io/livezip/

Guide What it covers
Getting started The source-agnostic recipe and the mental model.
Byte streams FileStream, UrlStream, BytesStream, S3Stream, and the lazy-open contract.
Storage strategies Store, DeflateStore, PrecompressedDeflate, and writing your own.
Streaming from S3 The logs-to-ZIP recipe and the object-metadata contract.
Architecture Modules, complexity, and serving over HTTP.
The ZIP format The PKZIP/ZIP64 records on the wire.
Encoding pipeline Segments, offsets, and the streaming trick.
Command line The livezip console script.
Testing Unit tests and the SeaweedFS end-to-end suite.
Contributing Develop, test and release.

Install

LiveZip needs Python 3.11 or newer and is managed with uv.

uv add "livezip[s3] @ git+https://github.com/OffworldNexus/livezip"

Once 1.0 is on PyPI:

uv add livezip            # core, zero runtime dependencies
uv add "livezip[s3]"      # with the S3 integration (boto3)
# or: pip install "livezip[s3]"

Quick start

Every archive is built the same way, regardless of where the bytes live: pick a source, pick a storage strategy, wrap each file in a ZipFile, then prepare() to learn the exact size and get_data() to stream it.

from datetime import UTC, datetime
from pathlib import Path

from livezip import BytesStream, FileStream, Store, ZipEncoder, ZipFile

when = datetime.now(UTC)
clip = Path("clip.mp4")
manifest = b'{"generated": true}'

encoder = ZipEncoder(
    [
        # from disk
        ZipFile(
            "clip.mp4",
            Store(FileStream(clip), clip.stat().st_size),
            when,
            is_binary=True,
        ),
        # from memory
        ZipFile(
            "manifest.json",
            Store(BytesStream(manifest), len(manifest)),
            when,
            is_binary=True,
        ),
    ]
)
encoder.prepare()
print(encoder.file_size)  # exact, before any read

for chunk in encoder.get_data():  # sources are opened one at a time
    ...

Swapping FileStream for UrlStream, BytesStream or S3Stream is the only change needed to read from a different backend — the strategies, offsets and predicted size are identical. See Getting started and Byte streams.

Logs in S3 → ZIP

A bucket holds log files that were DEFLATE-compressed at upload time, each carrying its original size and CRC32 in object metadata. Listing the bucket is then enough to build a perfectly-sized archive, and the payloads stream straight through — no re-compression, no extra download.

from livezip.s3 import create_client, zip_from_s3

client = create_client(region_name="eu-west-3")

# Lists the prefix (one HEAD per object) — no payload is downloaded yet.
encoder = zip_from_s3(client, "my-logs", prefix="2026/")
print(encoder.file_size)  # the exact archive size, already known

for chunk in encoder.get_data():  # only now are objects fetched, one at a time
    response.write(chunk)

A runnable, commented version lives in examples/s3_to_zip.py; see the S3 guide for the metadata contract and operational details.

Command line

livezip -o archive.zip photo.jpg video.mp4 notes.txt
livezip -m store -o raw.zip blob.bin                       # copy bytes verbatim
livezip --s3-bucket my-logs --s3-prefix 2026/ -o logs.zip  # bucket of DEFLATE logs
livezip --s3-bucket my-logs > logs.zip                     # stream to stdout

Project layout

src/livezip/
├── encode.py     # ZipEncoder + segments (the streaming core)
├── storage.py    # Store / DeflateStore / PrecompressedDeflate
├── stream.py     # FileStream / UrlStream / BytesStream
├── s3.py         # optional S3 integration (boto3 behind a protocol)
├── models.py     # PKZIP/ZIP64 record serialisation
└── cli.py        # the `livezip` console script
tests/            # unit + SeaweedFS-backed end-to-end suites
doc/              # Zensical documentation site

Development

Everything goes through uv; the Makefile is the entry point:

make sync        # install all dependencies (including the s3 extra)
make clean       # format then lint (ruff) and type-check (mypy)
make test        # unit + end-to-end (the latter needs Docker)
make coverage    # run with a coverage report
make docs-serve  # preview the documentation on localhost:8000
make build       # build sdist + wheel

See Contributing for the full workflow, the lint rules, and how releases are published.

License

WTFPL — do what the fuck you want to. See LICENSE.

Metadata

Release files for livezip 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for livezip 1.0.0
File Size Uploaded
livezip-1.0.0.tar.gz 32.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for livezip 1.0.0
File Interpreter ABI Platform
livezip-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 59.9 kB

Release files / livezip-1.0.0.tar.gz

Download URL livezip-1.0.0.tar.gz
Size 32.6 kB
Tags Source
SHA-256 checksum
How to use checksums
37aeefc9030b84b4220bb5f0f5086af360ea38dc91ffdc3d156082c0935e0f86
BLAKE2b-256 checksum
How to use checksums
0438b7e9229b9dab722f20c8f15bd6de74dc517acd5bde36de840e7cd8616c34
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / livezip-1.0.0-py3-none-any.whl

Download URL livezip-1.0.0-py3-none-any.whl
Size 27.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
70d57367543608c0888172d9144f179b2e058738fff8c4f85715eedfe7a1cdf4
BLAKE2b-256 checksum
How to use checksums
88ce2ddd6ace01a1b88228f53d16331f701dec24fb0a3bda18fafa00c3c8b68f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.23 {"installer":{"name":"uv","version":"0.12.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page