{"library":"zopfli","title":"Zopfli for Python","description":"Python bindings to the Zopfli Compression Algorithm, offering higher compression ratios than standard zlib or gzip at the cost of significantly slower compression time. It is primarily designed for pre-compressing static assets for web applications or other scenarios where file size is critical and compression is a one-off or build-time operation. Current version 0.4.1 requires Python 3.10+ and maintains an active release cadence, primarily driven by Python version compatibility and updates to the upstream C library.","status":"active","version":"0.4.1","language":"en","source_language":"en","source_url":"https://github.com/fonttools/py-zopfli","tags":["compression","zlib","gzip","png","optimization","zopfli","data compression"],"install":[{"cmd":"pip install zopfli","lang":"bash","label":"Install latest stable version"}],"dependencies":[],"imports":[{"note":"For Zlib-compatible compression.","symbol":"compress","correct":"from zopfli.zlib import compress"},{"note":"For Gzip-compatible compression.","symbol":"compress","correct":"from zopfli.gzip import compress"},{"note":"For lossless PNG optimization.","symbol":"optimize","correct":"from zopfli.png import optimize"}],"quickstart":{"code":"from zopfli.zlib import compress\nfrom zopfli.gzip import compress as gzip_compress\nimport zlib\nfrom io import BytesIO\nimport gzip\n\ndata = b\"Hello World! This is some data to compress using Zopfli.\\n\" * 10\n\n# Zlib compression\nzlib_compressed_data = compress(data, numiterations=15)\nprint(f\"Original size: {len(data)} bytes\")\nprint(f\"Zlib compressed size: {len(zlib_compressed_data)} bytes\")\nassert zlib.decompress(zlib_compressed_data) == data\n\n# Gzip compression (note: does not mimic gzip module API directly)\ngzip_compressed_data = gzip_compress(data, numiterations=15)\nprint(f\"Gzip compressed size: {len(gzip_compressed_data)} bytes\")\nwith gzip.GzipFile(fileobj=BytesIO(gzip_compressed_data)) as f:\n    assert f.read() == data\n\n# PNG optimization (example, requires an actual PNG file)\n# from zopfli.png import optimize\n# try:\n#     with open('input.png', 'rb') as f_in:\n#         optimized_png_data = optimize(f_in.read())\n#     with open('output_optimized.png', 'wb') as f_out:\n#         f_out.write(optimized_png_data)\n#     print(\"PNG optimized successfully.\")\n# except FileNotFoundError:\n#     print(\"Skipping PNG optimization: 'input.png' not found.\")","lang":"python","description":"Demonstrates basic Zopfli compression using both zlib and gzip formats, including decompression with standard library modules. Also provides a commented example for PNG optimization."},"warnings":[{"fix":"Upgrade Python to 3.10+ or pin `zopfli` to a compatible version (e.g., `<0.3.0` for Python 3.8/3.9).","message":"Python 3.8 and 3.9 support was dropped in v0.3.0, now requiring Python 3.10 or greater. Similarly, Python 3.7 was dropped in v0.2.3 and 2.7/3.6 in v0.2.0. Users on older Python versions must use an earlier `zopfli` release.","severity":"breaking","affected_versions":"<0.3.0"},{"fix":"Most users should be unaffected. If you encounter issues, verify your build chain or environment's compatibility with `abi3` wheels. Rebuilding from source might be necessary in niche cases.","message":"Starting from v0.4.0, `zopfli` utilizes CPython's `Py_LIMITED_API` to build `abi3`-tagged wheels. While this reduces the number of wheels and simplifies future Python version compatibility, it might affect users with highly specific CPython ABI requirements or custom build environments.","severity":"breaking","affected_versions":">=0.4.0"},{"fix":"Use Zopfli for pre-compressing static assets during a build process or deployment, rather than during a user request. Serve pre-compressed files with appropriate `Content-Encoding` headers.","message":"Zopfli compression is significantly slower than standard `zlib` or `gzip` (often 100x slower) but yields better compression ratios. It is generally not suitable for on-the-fly compression of dynamic content in web servers.","severity":"gotcha","affected_versions":"All"},{"fix":"Experiment with `numiterations` to find the optimal balance for your specific use case. Be mindful of the performance implications.","message":"The `numiterations` parameter (available for `zopfli.zlib.compress` and `zopfli.gzip.compress`) controls the compression effort. Higher values (e.g., 10-15 for small files) result in better compression but drastically increase processing time. For files over several MB, values around 5 are recommended to balance compression and speed.","severity":"gotcha","affected_versions":"All"},{"fix":"When decompressing output from `zopfli.gzip.compress`, use `gzip.GzipFile(fileobj=io.BytesIO(compressed_data)).read()` to ensure correct handling.","message":"The `zopfli.gzip.compress` function does not perfectly mimic the standard library's `gzip` module API for file-like objects or streaming. Decompression of `zopfli.gzip.compress` output typically requires wrapping it with `io.BytesIO` and then `gzip.GzipFile` to read.","severity":"gotcha","affected_versions":"All"},{"fix":"Upgrade to `zopfli` v0.4.1 or newer to benefit from the bug fix and ensure compatibility on strict-alignment architectures.","message":"As of v0.4.1, the underlying C `google/zopfli` submodule was switched to the `fonttools/zopfli` fork because the Google repository was archived. This change addresses an unaligned memory access issue that caused `SIGBUS` errors on strict-alignment architectures (e.g., SPARC).","severity":"gotcha","affected_versions":"<0.4.1"}],"env_vars":null,"last_verified":"2026-04-05T00:00:00.000Z","next_check":"2026-07-04T00:00:00.000Z"}