Skip to main content

Fast GZIP-to-ZIP/ZIP64 conversion without recompression

Project description

gz2zip

CI PyPI version Python versions

gz2zip converts GZIP to ZIP/ZIP64 without recompression by reusing the original Deflate payload.

This is much faster than decompressing and re-zipping, and it supports both:

  1. seekable file conversion (gzip_to_zip)
  2. streaming conversion (stream_gzip_to_zip) for pipes and async workloads

Benchmark

Benchmark: 100 MiB text, 5 iterations
Platform: macOS 26.0.1 (arm64)
CPU: Apple M1 Pro
Memory: 32.0 GiB
Python: 3.12.0
Input: 100.00 MiB text -> 30.49 MiB gzip

gz2zip.core.gzip_to_zip  mean 9.73 ms  median 9.69 ms  min 9.32 ms  max 10.48 ms
python gzip + zipfile    mean 3316.88 ms  median 3313.52 ms  min 3299.16 ms  max 3335.05 ms
shell gzip -dc | zip     mean 3390.16 ms  median 3385.02 ms  min 3361.35 ms  max 3435.71 ms

See benchmarks/speed_experiment.py for the benchmark script.

Installation

pip install gz2zip

Install as an isolated CLI tool with pipx:

pipx install gz2zip

or with uv:

uv tool install gz2zip

Run without installing globally:

pipx run gz2zip --help
uvx gz2zip --help

Supported Python versions

Based on the official Python version support table, this package targets:

  • Python 3.10
  • Python 3.11
  • Python 3.12
  • Python 3.13
  • Python 3.14

CLI Usage

The package installs the gz2zip command:

gz2zip INPUT_GZ [-o OUTPUT_ZIP] [-n NAME_IN_ZIP] [-s UNCOMPRESSED_SIZE] [-t ISO_TIMESTAMP] [-q]

Common examples

Convert a file and auto-derive output name (input.gz -> input.zip):

gz2zip input.gz

Set output path and internal filename:

gz2zip input.gz -o output.zip -n data.csv

Pipe from stdin to stdout:

cat input.gz | gz2zip - -n data.csv > output.zip

Large-file case (>4 GiB original content): provide exact uncompressed size:

gz2zip huge.sql.gz -o huge.zip -n huge.sql -s 5368709120

Run as a module:

python -m gz2zip input.gz -o output.zip

CLI options

Option Description
input Input .gz file. Use - (or omit) to read from stdin.
-o, --output Output ZIP file. Use - for stdout.
-n, --name Filename to store inside ZIP.
-s, --size Known uncompressed size (recommended for >4 GiB input).
-t, --timestamp Override timestamp in ISO 8601, e.g. 2025-12-31T23:59:58.
-q, --quiet Suppress non-error logs.

API Usage

Synchronous (seekable files)

from gz2zip import gzip_to_zip

with open("input.gz", "rb") as f_in, open("output.zip", "wb") as f_out:
    gzip_to_zip(f_in, f_out, filename_in_zip="data.csv")

Asynchronous streaming

import asyncio
from gz2zip import stream_gzip_to_zip

async def gzip_chunks():
    with open("input.gz", "rb") as f:
        while chunk := f.read(64 * 1024):
            yield chunk

async def main():
    with open("output.zip", "wb") as out:
        async for chunk in stream_gzip_to_zip(gzip_chunks(), "data.csv"):
            out.write(chunk)

asyncio.run(main())

ZIP64 note

GZIP stores ISIZE modulo 2^32, so files larger than 4 GiB need an explicit known_uncompressed_size (-s in CLI) if exact size metadata is required.

Limitation: concatenated GZIP members

Concatenated GZIP streams are valid (for example: cat a.gz b.gz > joined.gz), but this project currently does not support that multi-member format correctly. Use single-member .gz input files.

Development

Run tests:

uv run pytest

Project details


Download files

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

Source Distribution

gz2zip-0.1.0.post1.tar.gz (17.6 kB view details)

Uploaded Source

Built Distribution

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

gz2zip-0.1.0.post1-py3-none-any.whl (11.1 kB view details)

Uploaded Python 3

File details

Details for the file gz2zip-0.1.0.post1.tar.gz.

File metadata

  • Download URL: gz2zip-0.1.0.post1.tar.gz
  • Upload date:
  • Size: 17.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gz2zip-0.1.0.post1.tar.gz
Algorithm Hash digest
SHA256 938de4cdf5c9ad7a17aa65f1337eedb04c8f7e9ee5585cade433c310264b3460
MD5 c2ce91efdf93dc245c9eaf08ecbcf079
BLAKE2b-256 1bfbdd5edb52ebac78ac802cbc755598ce7598b3d51b45dc385127836b45d2a8

See more details on using hashes here.

Provenance

The following attestation bundles were made for gz2zip-0.1.0.post1.tar.gz:

Publisher: ci.yaml on 45deg/gz2zip

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

File details

Details for the file gz2zip-0.1.0.post1-py3-none-any.whl.

File metadata

  • Download URL: gz2zip-0.1.0.post1-py3-none-any.whl
  • Upload date:
  • Size: 11.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for gz2zip-0.1.0.post1-py3-none-any.whl
Algorithm Hash digest
SHA256 aca71cc0b006450c6c96de37941c2923f1afa8514149f643592ee3d6a7bee096
MD5 61f1a9db0c843d2b4aab354062bc61ae
BLAKE2b-256 871f99bbc61429082da1902c741362264465da65a99c25377239f103ff799207

See more details on using hashes here.

Provenance

The following attestation bundles were made for gz2zip-0.1.0.post1-py3-none-any.whl:

Publisher: ci.yaml on 45deg/gz2zip

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

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page