zipp
raw JSON → 3.23.0 verified Tue May 12 auth: no python install: stale quickstart: verified
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).
pip install zipp Common errors
error ModuleNotFoundError: No module named 'zipp' ↓
cause The 'zipp' package has not been installed in the current Python environment.
fix
pip install zipp
error ImportError: cannot import name 'path' from 'zipp' ↓
cause The 'Path' class in the 'zipp' package is named with an uppercase 'P'.
fix
from zipp import Path
error zipfile.BadZipFile: File is not a zip file ↓
cause The 'zipp.Path' object was initialized with a path to a file that is not a valid ZIP archive. 'zipp.Path' is designed to navigate *within* a ZIP file, not to represent regular filesystem paths.
fix
Ensure 'zipp.Path' is initialized with a path to a valid ZIP archive file (e.g., 'my_archive.zip') and then navigate inside it. For regular filesystem paths, use 'pathlib.Path' instead.
error IsADirectoryError: 'directory_name' ↓
cause A method like 'read_text()' or 'read_bytes()' was called on a 'zipp.Path' object that points to a directory within the ZIP archive, not an actual file.
fix
Navigate to a specific file within the directory (e.g., 'path / 'filename.txt'') before calling read methods.
Warnings
breaking zipp.Path.open() changed to text mode by default and dropped positional pwd and force_zip64 parameters. ↓
fix Pass mode='rb' explicitly for binary reads. Remove any positional pwd argument; keyword args still pass through to io.TextIOWrapper.
breaking Path.joinpath() dropped the 'add' keyword argument; it now only accepts arbitrary positional path segments. ↓
fix Replace joinpath(add='sub/path') with joinpath('sub/path') or the / operator (root / 'sub' / 'path').
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. ↓
fix Pin to zipp<3.20 if you must support Python 3.8. For Python 3.7, pin to zipp<3.5.
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. ↓
fix Use path.name (strips the slash) rather than str(path) when comparing directory names.
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. ↓
fix Do not rely on the original ZipFile object type after wrapping it in zipp.Path; use the zipp.Path interface exclusively for all navigation.
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. ↓
fix Filter results with item.is_file() when you want only files: [p for p in root.glob('**/*.txt') if p.is_file()].
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. ↓
fix Declare a loose lower bound (zipp>=3.9) rather than an exact pin unless you have a specific compatibility reason.
Install compatibility stale last tested: 2026-05-12
python os / libc status wheel install import disk
3.10 alpine (musl) - - - -
3.10 slim (glibc) - - - -
3.11 alpine (musl) - - - -
3.11 slim (glibc) - - - -
3.12 alpine (musl) - - - -
3.12 slim (glibc) - - - -
3.13 alpine (musl) - - - -
3.13 slim (glibc) - - - -
3.9 alpine (musl) - - - -
3.9 slim (glibc) - - - -
Imports
- Path wrong
from zipfile import Pathcorrectimport zipp; path = zipp.Path('archive.zip') - zipp.compat.overlay
import zipp.compat.overlay
Quickstart verified last tested: 2026-04-23
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)