zipp
zipp is the official backport of the pathlib-compatible zipfile.Path object from the Python standard library. It provides a Traversable/pathlib-like interface for navigating and reading ZIP archives (zipp.Path), with new features introduced here first and later merged into CPython. Current version is 3.23.0, released June 2025, with a very active cadence of roughly one release per month maintained by Jason R. Coombs (jaraco).
Warnings
- breaking zipp.Path.open() changed to text mode by default and dropped positional pwd and force_zip64 parameters.
- breaking Path.joinpath() dropped the 'add' keyword argument; it now only accepts arbitrary positional path segments.
- breaking Requires Python >=3.9 as of recent releases. Older zipp releases supported Python 3.6/3.7/3.8 but those branches are no longer maintained.
- gotcha Directory entries from iterdir() always end with a trailing slash in their string representation. Comparing path names with string equality will fail unless you strip the slash.
- gotcha Passing a ZipFile object to zipp.Path mutates the ZipFile in place (converts it to a CompleteDirs subclass). The caller's reference is affected. This is by design to prevent double-close bugs.
- gotcha Path.glob('**') previously did not match directories; since 3.20 it does. Code that relied on glob returning only files may now receive unexpected directory entries.
- gotcha zipp is commonly pulled in as a transitive dependency (e.g. by importlib-metadata, pip, pytest). Pinning it too tightly in lock files can block upgrades of those tools.
Install
-
pip install zipp
Imports
- Path
import zipp; path = zipp.Path('archive.zip') - zipp.compat.overlay
import zipp.compat.overlay
Quickstart
import io
import zipfile
import zipp
# Build an in-memory zip
data = io.BytesIO()
with zipfile.ZipFile(data, 'w') as zf:
zf.writestr('hello.txt', 'Hello, zipp!')
zf.writestr('sub/world.txt', 'World!')
zf.filename = 'example.zip'
# Navigate with zipp.Path (pathlib-style)
root = zipp.Path(data)
for item in root.iterdir():
print(item.name, item.is_file())
# Read a nested file
file_path = root / 'hello.txt'
print(file_path.read_text()) # 'Hello, zipp!'
# Glob support
for txt in root.glob('**/*.txt'):
print(txt)