Skip to main content

package-python-function

Python command-line (CLI) tool to package a Python function for deploying to AWS Lambda, and possibly other cloud platforms.

This tool builds a ZIP file from a virtual environment with all dependencies installed that are to be included in the final deployment asset. If the content is larger than AWS Lambda's maximum unzipped package size of 250 MiB, This tool will then employ the ZIP-inside-ZIP (nested-ZIP) workaround. This allows deploying Lambdas with large dependency packages, especially those with native code compiled extensions like Pandas, PyArrow, etc. The ZIP files are generated reproducibly, ensuring that the same source will always generate a ZIP file with the same hash.

This technique was originally pioneered by serverless-python-requirements, which is a NodeJS (JavaScript) plugin for the Serverless Framework. The technique has been improved here to not require any special imports in your entrypoint source file. That is, no changes are needed to your source code to leverage the nested ZIP deployment.

The motivation for this Python tool is to achieve the same results as serverless-python-requirements but with a purely Python tool. This can simplify and speed up developer and CI/CD workflows.

One important thing that this tool does not do is build the target virtual environment and install all of the dependencies. You must first generate that with a tool like Poetry and the poetry-plugin-bundle.

Example command sequence

poetry bundle venv .build/.venv --without dev
package-python-function .build/.venv --output-dir .build/lambda

The output will be a .zip file named after your project, as described in Output file name.

Installation

Use pipx to install:

pipx install package-python-function

Usage / Arguments

package-python-function venv_dir [--project PROJECT] [--output-dir OUTPUT_DIR] [--output OUTPUT] [--report REPORT]
  • venv_dir [Required]: The path to the virtual environment to package.
  • --project [Optional]: Path to the pyproject.toml file. Omit to use the pyproject.toml file in the current working directory.
  • --report [Optional]: Path to write a JSON report file to. Omit to write no report.

--output and --output-dir cannot be used together. If neither is given, the zip is written to the current working directory.

  • --output: The full output path of the final zip file.
  • --output-dir: The output directory for the final zip file. The name of the zip file is described in Output file name.

Output file name

Unless --output gives an exact path, the file written is <output-dir>/<distribution_name>.zip.

distribution_name is the project's name — [project].name, or [tool.poetry].name if that is absent — with each run of characters outside A-Z a-z 0-9 _ . replaced by a single underscore, following the PyPA escaping rules.

Case is preserved. A project named My-App produces My_App.zip, not my_app.zip. Note that this differs from the wheel your build tool produces for the same project, whose filename is lowercased — so a wheel's name is not a safe way to predict the name of this file.

Report file

Pass --report <path> to have the tool write a JSON description of what it produced, so a calling script does not have to re-derive the output path or re-measure the package.

{
  "output_file": "/abs/path/lambda/my_app.zip",
  "distribution_name": "my_app",
  "output_bytes": 3460000,
  "uncompressed_bytes": 412000000,
  "compressed_bytes": 3456789,
  "nested_zip": false
}
Field Meaning
output_file Absolute path of the zip that was written.
distribution_name The normalized project name, as described in Output file name.
output_bytes Size of the file at output_file. This is the artifact you deploy.
uncompressed_bytes Total size of the packaged files before compression. This is the figure compared against the AWS Lambda 250 MiB unzipped limit.
compressed_bytes Size of the dependencies zip. Equal to output_bytes unless the nested-zip strategy was used, in which case the outer zip also holds the loader.
nested_zip Whether the nested-zip strategy was used.

The report is written only when packaging succeeds, so its presence is a reliable signal that the zip is really there.

Notes on Reproducibility

Timestamps

The ZIP files generated adhere with reproducible builds. This means that file permissions and timestamps are modified inside the ZIP, such that the ZIP will have a deterministic hash. By default, the date is set to 1980-01-01.

Additionally, the tool respects the standardized $SOURCE_DATE_EPOCH environment variable, which will allow you to set that date as needed.

One important caveat is that ZIP files do not support files with timestamps earlier than 1980-01-01 inside them, due to MS-DOS compatibility. Therefore, the tool will throw a SourceDateEpochError is $SOURCE_DATE_EPOCH is below 315532800.

Files with embedded full paths

In testing, we found that several file types can leak information from the machine that generated the virtual environment.

To get around this, the tool removes the following files:

**/__pycache/
**/*.dist-info/direct_url.json
**/*.dist-info/RECORD
**/*.pyc
**/*.pyo

Metadata

Release files for package-python-function 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for package-python-function 1.0.0
File Size Uploaded
package_python_function-1.0.0.tar.gz 9.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for package-python-function 1.0.0
File Interpreter ABI Platform
package_python_function-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 21.8 kB

Release files / package_python_function-1.0.0.tar.gz

Download URL package_python_function-1.0.0.tar.gz
Size 9.5 kB
Tags Source
SHA-256 checksum
How to use checksums
f87365a2da5ee7158a01c6f0a6fff1cc813b97e1a79e47ee4796f5e8160f81e9
BLAKE2b-256 checksum
How to use checksums
a18e5d82b6b90144b2419ef3d305dfa99b2a2f9a03d1a5c54e266e422f836876
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.

Transparency log

Release files / package_python_function-1.0.0-py3-none-any.whl

Download URL package_python_function-1.0.0-py3-none-any.whl
Size 12.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4a574f4c100cdfcc4cad61056b1c2c8b67364d462384290fc4c439988988664e
BLAKE2b-256 checksum
How to use checksums
bbbc3f470b42d60b38efdbfa31657645a9b29c469c6e578af3940e3f31ca05b2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

0.0.11

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page