Skip to main content

bytehaul

Python bindings for the bytehaul Rust download library. This guide targets the published 0.2.3 release.

中文使用文档

Requirements

  • Python 3.9+
  • Rust toolchain and uv only when building from source; neither is required to install an available wheel.

Each source-build command block below assumes you start from the repository root.

Installation

From PyPI

pip install "bytehaul==0.2.3"

See the 0.2.3 release notes.

From source (development)

uv sync --project bindings/python
cd bindings/python
uv run --project . maturin develop -m Cargo.toml

Build wheel

cd bindings/python
uv run --project . maturin build --release -m Cargo.toml

Usage

Simple download

import bytehaul

bytehaul.download("https://example.com/file.bin", output_path="output.bin")

# Let bytehaul decide the filename and place it in downloads/
bytehaul.download("https://example.com/file.bin", output_dir="downloads")

With options

bytehaul.download(
    "https://example.com/file.bin",
    output_path="output.bin",
    max_connections=8,
    max_download_speed=1_000_000,  # 1 MB/s
    headers={"Authorization": "Bearer token"},
)

Network settings

bytehaul.download(
    "https://example.com/file.bin",
    output_path="output.bin",
    proxy="http://127.0.0.1:7890",
    dns_servers=["1.1.1.1", "8.8.8.8:53"],
    doh_servers=["https://dns.google/dns-query"],
    enable_ipv6=False,
)

doh_servers expects HTTPS URLs. If you pass a hostname such as dns.google, bytehaul will use the system resolver once during client construction to bootstrap the DoH endpoint addresses.

Logging

# Enable debug logging on the convenience function
bytehaul.download(
    "https://example.com/file.bin",
    output_path="output.bin",
    log_level="debug",
)

# Or on the Downloader object
from bytehaul import Downloader

downloader = Downloader(log_level="info")

Valid levels: "off" (default), "error", "warn", "info", "debug", "trace".

Object API with progress and cancellation

from bytehaul import Downloader

downloader = Downloader(
    connect_timeout=15.0,
    dns_servers=["1.1.1.1"],
    doh_servers=["https://dns.google/dns-query"],
    enable_ipv6=False,
)
task = downloader.download(
    "https://example.com/large.bin",
    output_dir="downloads",
    proxy="http://127.0.0.1:7890",
)

# Poll progress
snap = task.progress()
print(
    f"State: {snap.state}, Downloaded: {snap.downloaded}, "
    f"Speed: {snap.speed:.0f} B/s, ETA: {snap.eta_secs}"
)

# Pause or cancel if needed
# task.pause()
# task.cancel()

# Wait for completion
task.wait()

Error handling

from bytehaul import download, DownloadFailedError, CancelledError, PausedError, ConfigError

try:
    download("https://example.com/file.bin", output_path="output.bin")
except ConfigError as e:
    print(f"Invalid parameter: {e}")
except PausedError:
    print("Download was paused")
except CancelledError:
    print("Download was cancelled")
except DownloadFailedError as e:
    print(f"Download failed: {e}")

Response-body timeouts, connection resets and early EOF for a known-size body are retried within max_retries, which counts additional attempts after the first (0 disables retries). With a known total and matching object validators, continuation starts at the durable prefix confirmed by the writer; ignored Range requests or changed object metadata trigger a safe restart from zero. Disk write and synchronization errors are not retried as network failures.

API Reference

download(url, output_path=None, output_dir=None, **options)

Blocking convenience function. Downloads a file and returns when complete.

  • output_path: explicit filename or relative output path
  • output_dir: destination directory for explicit or auto-detected filenames
  • If output_path is omitted, bytehaul chooses Content-Disposition → URL path → download
  • Absolute output_path values are still accepted when output_dir is omitted

Downloader(connect_timeout=None, proxy=None, http_proxy=None, https_proxy=None, dns_servers=None, doh_servers=None, enable_ipv6=None, log_level=None)

Reusable downloader instance.

  • downloader.download(url, output_path=None, output_dir=None, **options) -> DownloadTask

Proxy settings passed to Downloader(...) act as defaults. You can override them per task by passing proxy, http_proxy, or https_proxy directly to downloader.download(...).

DownloadTask

Handle to a running download.

  • task.progress() -> ProgressSnapshot — current download progress
  • task.pause() — pause the download and persist resume metadata when available
  • task.cancel() — cancel the download
  • task.wait() — block until download completes (releases GIL)

wait() consumes the task handle. It cannot be called twice, and progress() is unavailable after it returns or raises.

ProgressSnapshot

Frozen snapshot of download progress.

Attribute Type Description
total_size int | None Total file size (if known)
downloaded int UI-oriented received bytes, not a durable resume offset
state str "pending", "downloading", "completed", "failed", "cancelled", "paused"
speed float Recent-window speed in bytes/second
eta_secs float | None Estimated remaining seconds
elapsed_secs float | None Elapsed time in seconds

downloaded may decrease during retries or already equal total_size when final synchronization fails. Final write or synchronization failures produce failed state, and the control file retains only confirmed durable progress. Use the result or exception from task.wait() to determine success; do not use the displayed byte count as a resume offset.

speed and eta_secs are computed from the same recent throughput window. speed is not a whole-download lifetime average, and eta_secs stays None until bytehaul has enough recent samples or a known total size.

Download options

Parameter Type Default
output_path str | Path | None None
output_dir str | Path | None None
headers dict[str, str] {}
max_connections int 4
connect_timeout float (secs) 30.0
read_timeout float (secs) 60.0
memory_budget int 67108864
file_allocation "none" | "prealloc" "prealloc"
resume bool True
piece_size int 1048576
min_split_size int 10485760
max_retries int 5
retry_base_delay float (secs) 1.0
retry_max_delay float (secs) 30.0
max_retry_elapsed float | None (secs) None
control_save_interval float (secs) 5.0
autosave_sync_every int 2
max_download_speed int 0 (unlimited)
checksum_sha256 str | None None
log_level str | None None ("off")

max_retries counts additional retries after the initial request/transfer attempt; 0 disables retries. Single-connection body failures resume from the writer's flushed contiguous prefix, while Range or object-metadata mismatches reset the file before restarting.

control_save_interval checks whether a checkpoint is due; autosave_sync_every batches those checks when unsaved progress exists. Set log_level on the convenience download(...) function or the Downloader(...) constructor.

Valid log_level values: "off", "error", "warn", "info", "debug", "trace" (case-insensitive).

Contiguous requests

Version 0.2.3 adds request_batch_size to both download APIs, after existing positional parameters. None or 0 keeps one lease per request; for example, request_batch_size=4 * 1024 * 1024 groups adjacent pieces into bounded Range requests. Completion/checkpoint granularity remains piece_size, with at most 64 leases per batch. Values below a piece do not split it, and grouping stops at completed/active/partially processed pieces.

Strong-ETag multi-connection transfers can also retain writer-confirmed prefixes on interrupted-body retries or adaptive reassignment. Incomplete pieces remain incomplete across process restarts. These engine behaviors apply to both Python entry points, while the experimental HTTP idle-pool option remains Rust-only.

Slow-transfer recovery

Available starting with version 0.2.2. These options apply to both download(...) and Downloader.download(...); None selects the Rust engine default.

Parameter Default Meaning
slow_transfer_mode "adaptive" "disabled", "adaptive", or "adaptive_with_hedging" (case-insensitive)
low_speed_limit None Optional positive absolute floor, bytes/second
low_speed_duration 15.0 Sustained low-speed time, seconds
slow_start_grace 5.0 Startup grace, seconds
slow_sample_window 5.0 Speed observation window, seconds

Durations must be finite, positive and at most 86,400 seconds. Adaptive recovery is on by default for multi-connection Range downloads. Hedging is opt-in, needs a strong ETag and a spare connection slot, and stages at most one small spare response before choosing a writer. It does not duplicate progress or exceed max_connections. All network payload shares the configured rate limit. Performance recovery and hedging together reserve at most min(total_size / 100, 16 MiB) of extra Range work; requests that do not fit are skipped. Normal error retries use the existing retry policy.

from bytehaul import Downloader

task = Downloader(log_level="debug").download(
    "https://example.com/file.bin",
    "file.bin",
    slow_transfer_mode="adaptive_with_hedging",
)
task.wait()

Use slow_transfer_mode="disabled" to disable performance-triggered cancellation and hedging. Single-connection and non-Range fallback behavior is unchanged. Recovery excludes intentional rate limiting and local backpressure; it cannot remove a shared origin bandwidth limit.

When max_download_speed is nonzero, automatic slow-request recovery and hedging are suppressed to avoid treating intentional rate limiting as a network fault. Ordinary timeouts and error retries still apply.

Network options

Use these on Downloader(...) to set defaults, or pass proxy, http_proxy, and https_proxy directly to downloader.download(...) or the blocking download(...) helper.

Parameter Type Default
proxy str | None None
http_proxy str | None None
https_proxy str | None None
dns_servers list[str] | None None
doh_servers list[str] | None None
enable_ipv6 bool | None True

Running tests

uv sync --project bindings/python
cd bindings/python
uv run --project . maturin develop -m Cargo.toml
uv run --no-sync --project . pytest tests/ -v

After maturin develop, use --no-sync for tests so uv does not replace the freshly built development extension during another environment sync.

Building wheels for release

Single platform:

cd bindings/python
uv run --project . maturin build --release -m Cargo.toml

Cross-platform (via CI):

# Linux x86_64 + aarch64, macOS x86_64 + arm64, Windows x86_64
# Use maturin's GitHub Actions: https://github.com/PyO3/maturin-action

The project uses abi3-py39, so a single wheel per platform covers all Python 3.9+ versions.

License

MIT. See the repository LICENSE file.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bytehaul-0.2.3.tar.gz (267.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

bytehaul-0.2.3-cp39-abi3-win_amd64.whl (3.0 MB view details)

Uploaded CPython 3.9+Windows x86-64

bytehaul-0.2.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.5 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

bytehaul-0.2.3-cp39-abi3-macosx_11_0_arm64.whl (3.1 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

bytehaul-0.2.3-cp39-abi3-macosx_10_12_x86_64.whl (3.2 MB view details)

Uploaded CPython 3.9+macOS 10.12+ x86-64

File details

Details for the file bytehaul-0.2.3.tar.gz.

File metadata

  • Download URL: bytehaul-0.2.3.tar.gz
  • Upload date:
  • Size: 267.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for bytehaul-0.2.3.tar.gz
Algorithm Hash digest
SHA256 9711de9f9e9678af542a6dbdc3678637a2361b5e497e41704a64189665a693fa
MD5 900c2686e5bb881d18922e0255f1b959
BLAKE2b-256 baf40e53deaba4f41a468901caa783be62bece9239c60d34da1a11350867379d

See more details on using hashes here.

Provenance

The following attestation bundles were made for bytehaul-0.2.3.tar.gz:

Publisher: publish-pypi.yml on triwinds/bytehaul

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bytehaul-0.2.3-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: bytehaul-0.2.3-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 3.0 MB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for bytehaul-0.2.3-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 a0fa8b7afbf7d6d322c69beacfb5d6e15181ea8a72d63ece0c42f6c6b2ec0068
MD5 9f548c0f29334ad27c53002dd3b7670a
BLAKE2b-256 fd90a63fc9743dcf6a5b8dd765ec319e394e2d4fef9e9bcd2666f670601ec3a7

See more details on using hashes here.

Provenance

The following attestation bundles were made for bytehaul-0.2.3-cp39-abi3-win_amd64.whl:

Publisher: publish-pypi.yml on triwinds/bytehaul

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bytehaul-0.2.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for bytehaul-0.2.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 5c02c734f85a2cee27c8ebbc4158193df522f57e36f4c75bbae526b4cb698bf6
MD5 6487ee23c84ea9113798d858e8ea6fd2
BLAKE2b-256 c56fbc29b0d2969ad507d2922da9d8b0cf9278ea5d4f59ec0a7a74c41e861116

See more details on using hashes here.

Provenance

The following attestation bundles were made for bytehaul-0.2.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish-pypi.yml on triwinds/bytehaul

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bytehaul-0.2.3-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for bytehaul-0.2.3-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 23267a5805146e51bf73e83322a61c5c0a18afc261af267d99f8cb46aca78a88
MD5 c380bdb1494c32f617a4b877ace7b56f
BLAKE2b-256 e064a630aadd2338a192bee523cd3394bb75ca56242fcff2d0d9bf960bcdb22c

See more details on using hashes here.

Provenance

The following attestation bundles were made for bytehaul-0.2.3-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: publish-pypi.yml on triwinds/bytehaul

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bytehaul-0.2.3-cp39-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for bytehaul-0.2.3-cp39-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 34fc1ac6a6991eae98ec16b684eccdac96ac7b5b0f0e1dda391745a461609208
MD5 9ccb9adef5c73ae08b389a4b2695ea5b
BLAKE2b-256 6689d48cb2f5dbfebc499f9a81326ef40a92f616069956731596652b2bcb1aa2

See more details on using hashes here.

Provenance

The following attestation bundles were made for bytehaul-0.2.3-cp39-abi3-macosx_10_12_x86_64.whl:

Publisher: publish-pypi.yml on triwinds/bytehaul

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.2.6

5 files

0.2.5

5 files

0.2.4

5 files

This release

0.2.3 This release

5 files

0.2.2

5 files

0.2.1

5 files

0.2.0

5 files

0.1.9

5 files

0.1.8

5 files

0.1.7

5 files

0.1.6

5 files

0.1.5

5 files

0.1.4

5 files

0.1.3

5 files

0.1.2

5 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