A zipapp is a ZIP archive with a Python entrypoint that a compatible interpreter can execute as an application.
Python zipapp: build an executable archive without bundling an interpreter
Operation contract
The fixture writes one owned __main__.py module, builds a compressed archive and executes it in a child interpreter with explicit arguments. The subprocess checks its exit code and expected output. The archive is deleted with its temporary directory and is not published to a package registry.
Failure and ownership boundary
The archive does not contain Python itself, and third-party/native extension dependencies need a separate distribution strategy. A .pyz file is executable code, not a safe data document to inspect by running it. The example uses only source it just wrote. Python package layout: owned imports and module entrypoints and Python subprocess: argument vectors, exit codes and bounded fixtures explain the surrounding behavior.
Working program
from pathlib import Path
import subprocess
import sys
import tempfile
import zipapp
from zipfile import ZipFile
with tempfile.TemporaryDirectory() as directory:
application = Path(directory) / "receipt_cli"
application.mkdir()
(application / "__main__.py").write_text(
'import sys\n'
'if len(sys.argv) != 2 or sys.argv[1] != "--region-count":\n'
' raise SystemExit(2)\n'
'print("supported regions: 2")\n', encoding="utf-8")
archive = Path(directory) / "receipt_cli.pyz"
zipapp.create_archive(application, archive, compressed=True)
result = subprocess.run([sys.executable, "-I", str(archive), "--region-count"],
cwd=directory, capture_output=True, text=True, timeout=5, check=True)
print(result.stdout.strip())
with ZipFile(archive) as built:
print("archive built:", "__main__.py" in built.namelist())Output
supported regions: 2
archive built: TrueCosts and limits
Archive creation scans and compresses supplied files; storage depends on their contents. Runtime imports may decompress source. This fixture has tiny fixed output and does not enforce a general child-output/process-tree budget.
Common Mistakes
- A zipapp needs a compatible external interpreter.
- Do not execute an untrusted archive merely to identify its format.
Connected lessons
Python package layout: owned imports and module entrypoints, Python subprocess: argument vectors, exit codes and bounded fixtures, Python package resources: read data from a ZIP-backed package.
