Zipbundler uses a JSONC (JSON with Comments) configuration file to control how packages are bundled. You can use either .zipbundler.jsonc in your project root or add configuration to pyproject.toml.
Important: Zipbundler produces zipapp-compatible .pyz files that:
zipimport or importlibzipapp moduleZipbundler looks for configuration in this order:
.zipbundler.jsonc in the current directorypyproject.toml under [tool.zipbundler]packages (required)Array of package paths or glob patterns to include in the zip.
{
"packages": [
"src/my_package/**/*.py",
"my_other_package",
"installed_package/**/*.py"
]
}
exclude (optional)Array of glob patterns for files/directories to exclude.
{
"exclude": [
"**/__pycache__/**",
"**/*.pyc",
"**/*.pyo",
"**/tests/**",
"**/.git/**",
"**/.*"
]
}
Default exclusions (always applied):
__pycache__/*.pyc, *.pyo.git/.hg/, .svn/output (optional)Output configuration for the zip file.
{
"output": {
"path": "dist/my_package.zip",
"directory": "build", // Optional: output directory (default: "dist")
"name": "my_package" // Optional: override zip name
}
}
path: Full path to output zip file (takes precedence over directory and name)directory: Output directory (default: "dist"). Used with name to generate path when path is not specifiedname: Optional name override for the zip file. When used with directory, generates {directory}/{name}.pyzentry_point (optional)Entry point for executable zip files (equivalent to -m / --main in zipapp-style CLI).
{
"entry_point": "my_package.__main__:main"
}
Format: module.path:function_name or module.path (for __main__.py)
When specified, zipbundler will generate code to call this function when the zip is executed. This is compatible with Python’s zipapp module entry point format.
options (optional)Various bundling options.
{
"options": {
"shebang": "/usr/bin/env python3", // Shebang line (default: "/usr/bin/env python3", set to false to disable)
"main_guard": true, // Insert if __name__ == "__main__" guard (default: true)
"compress": true, // Enable/disable compression (default: true)
"compression": "deflate", // Compression method: "deflate", "stored", "bzip2", "lzma" (default: "deflate")
"compression_level": 6, // Compression level 0-9 (default: 6, only for deflate)
"respect_gitignore": true // Respect .gitignore patterns (default: true)
}
}
shebang: Shebang line string (e.g., "/usr/bin/env python3") or false to disable. Equivalent to -p / --python in zipapp-style CLI.main_guard: If true, wraps entry point in if __name__ == "__main__": guardcompress: If true, compress the zip file; if false, store without compression (default: true). Can be overridden with CLI flags --compress or --no-compress.compression: Zip compression method (see Python’s zipfile module). Use "stored" for no compression (equivalent to --no-compress in zipapp-style CLI).compression_level: Compression level for deflate method (0-9, higher = more compression)respect_gitignore: If true, respect .gitignore patterns when selecting files (default: true). Can be overridden with CLI flags --gitignore or --no-gitignore.metadata (optional)Metadata included in the zip file’s PKG-INFO.
{
"metadata": {
"display_name": "My Package",
"description": "A great Python package",
"version": "1.0.0",
"author": "Your Name",
"license": "MIT"
}
}
Metadata Priority Chain:
Zipbundler uses a cascading priority system for metadata:
metadata field (highest priority)[project] sectionlicense: “All rights reserved. See additional license files if distributed alongside this file for additional terms.”This means metadata is always written to the zip when available from any source. The license field is guaranteed to be present (using the default fallback if not explicitly provided).
Example with pyproject.toml auto-detection:
If you have a pyproject.toml like this:
[project]
name = "my-package"
version = "1.0.0"
description = "A great Python package"
authors = [{name = "Your Name"}]
And no metadata field in your zipbundler config, the metadata will be automatically extracted from pyproject.toml and written to the zip with the default license fallback.
You can also configure zipbundler in pyproject.toml:
[tool.zipbundler]
packages = ["src/my_package/**/*.py"]
exclude = ["**/__pycache__/**", "**/tests/**"]
[tool.zipbundler.output]
path = "dist/my_package.zip"
[tool.zipbundler.options]
shebang = true
main_guard = true
compress = true
compression = "deflate"
respect_gitignore = true
[tool.zipbundler.metadata]
display_name = "My Package"
version = "1.0.0"
{
"packages": ["src/my_package"]
}
{
"packages": [
"src/my_package/**/*.py",
"src/utils/**/*.py"
],
"exclude": [
"**/__pycache__/**",
"**/*.pyc",
"**/tests/**",
"**/docs/**"
],
"output": {
"path": "dist/my_package.zip",
"directory": "build",
"name": "my_package"
},
"entry_point": "my_package.__main__:main",
"options": {
"shebang": true,
"main_guard": true,
"compress": true,
"compression": "deflate",
"compression_level": 9,
"respect_gitignore": true
},
"metadata": {
"display_name": "My Package",
"description": "A bundled Python package",
"version": "1.0.0"
}
}
Validate your configuration file:
zipbundler validate
This checks for: