zipfile
| Language | Python |
|---|---|
| License | PSF License (Python standard library) |
| Repository | github.com/python/cpython |
| Documentation | zipfile — Work with ZIP archives |
| Depends on | nothing (uses the bundled zlib, bz2, lzma, compression.zstd modules) |
| Read / write | yes / yes, ZIP64, stored, DEFLATE, bzip2, LZMA, Zstandard (3.14+); decrypts ZipCrypto only, can't encrypt |
zipfile reads, creates and appends to ZIP archives. ZipFile opens an archive in mode "r", "w", "a" (append) or "x" (create, fail if it exists); ZipInfo holds the metadata of one entry. zipfile.Path gives a pathlib-style interface for reading.
It can’t delete or replace entries in an existing archive (write a new one instead), can’t create encrypted archives and can’t read AES-encrypted ones. For AES, use the third-party pyzipper package, which has the same API.
Python also has a command-line interface: python -m zipfile -c out.zip folder/ and python -m zipfile -e in.zip out/.
Installation#
Nothing to install: part of the standard library.
Basic usage: extract and create a ZIP#
import zipfile
# extract everything
with zipfile.ZipFile("in.zip") as zf:
zf.extractall("out")
# create an archive
with zipfile.ZipFile("out.zip", "w", compression=zipfile.ZIP_DEFLATED, compresslevel=9) as zf:
zf.write("report.pdf", arcname="docs/report.pdf")
zf.writestr("hello.txt", "hello from Python\n")
extractall sanitizes names: it removes .. components and leading slashes, so files stay inside the target folder.
How to list the files in a ZIP#
import zipfile
with zipfile.ZipFile("in.zip") as zf:
for info in zf.infolist():
kind = "dir " if info.is_dir() else "file"
print(f"{kind} {info.filename:40} {info.file_size:>10} -> {info.compress_size:>10} {info.date_time}")
zf.namelist() returns only the names.
How to read one file without extracting#
import zipfile
with zipfile.ZipFile("in.zip") as zf:
text = zf.read("docs/readme.txt").decode("utf-8")
# or stream a large entry
with zf.open("data/big.csv") as f:
for line in f:
print(line.decode().rstrip())
How to zip a whole folder#
import shutil
shutil.make_archive("photos", "zip", root_dir="photos") # creates photos.zip
Or with control over each entry:
import pathlib
import zipfile
src = pathlib.Path("photos")
with zipfile.ZipFile("photos.zip", "w", zipfile.ZIP_DEFLATED) as zf:
for path in src.rglob("*"):
zf.write(path, arcname=path.relative_to(src))
How to extract a password-protected ZIP#
import zipfile
with zipfile.ZipFile("secret.zip") as zf:
zf.extractall("out", pwd=b"my password")
This works only for ZipCrypto. AES-encrypted entries raise NotImplementedError; open them with pyzipper.AESZipFile.
How to append to an existing ZIP#
import zipfile
with zipfile.ZipFile("existing.zip", "a") as zf:
zf.write("new.txt")
Writing a name that already exists adds a duplicate entry (with a warning); readers usually see the last one.
Tips#
zipfile.is_zipfile(path)checks for a valid end of central directory record.- Use
compression=zipfile.ZIP_STOREDfor already-compressed files (JPEG, MP4). - For archives made with old tools that use a DOS code page, pass
metadata_encoding="cp437"(or"cp866","shift_jis") when reading (Python 3.11+). zipfiledoesn’t restore Unix permissions on extract; the mode is ininfo.external_attr >> 16.