Skip to main content

A Windows-oriented CLI packer for Python projects using uv and the Python Embedded Runtime.

Project description

uvpacker

Windows-oriented CLI packer for Python projects using uv and the CPython Embedded Runtime; run it on Linux, macOS, or Windows to produce a self-contained win_amd64 app directory (not a single-file exe).

Python 3.12+ CI PyPI version GitHub stars

简体中文


Overview

uvpacker builds a directory you can zip or copy as-is. It contains:

  • the official CPython Embedded Runtime for Windows (64-bit)
  • your third-party dependencies installed for win_amd64
  • your project package embedded into each generated launcher .exe
  • launchers derived from [project.scripts] (console) and [project.gui-scripts] (no console window), as .exe when templates are available

The goal is to run on machines without a system Python, while keeping the build declarative (standard pyproject.toml) and predictable.

Repository: touken928/uvpacker

Requirements (target projects)

The project you pack must have:

Requirement Notes
pyproject.toml Standard layout
[project.scripts] and/or [project.gui-scripts] At least one entry; names must not overlap between the two tables
[build-system] Used to reproduce the build environment
project.requires-python Must be ==X.Y.* (e.g. ==3.11.*, ==3.12.*)

uvpacker picks the latest patch for that minor that has embed-amd64 on python.org.

Output layout

Default path: dist/<project-name>/

dist/<project-name>/
  runtime/          # Windows embedded CPython
  packages/         # Third-party dependencies only (win_amd64)
  <script>.exe      # Console vs GUI template from scripts / gui-scripts

Launchers load runtime\python3.dll, patch the embedded ._pth / .pth file so ..\packages is on sys.path, and import your project package from an archive appended to the end of the .exe — no dependency on a global Python install.

Installation & usage

Recommended: run with uvx.

# Build package output (default output: ./dist/<project-name>)
uvx uvpacker build path/to/project

# Explicit output directory
uvx uvpacker build path/to/project -o path/to/output

# Cache management
uvx uvpacker cache clear

uvpacker cache clear only removes embedded Python runtime cache (~/.cache/uvpacker/embed or $XDG_CACHE_HOME/uvpacker/embed); dependency-package cache is managed by uv.

Note: Tested with uv 0.11.x. Newer uv releases may change CLI behavior; report or pin versions if something breaks.

Examples

Path What it shows
example/web-demo FastAPI + importlib.resources for static assets
example/qt-demo PySide6 GUI via generated launcher
example/cli-demo Small argparse console tool for Python 3.14 (hello / version / cwd subcommands)

Cross-platform builds

Dependency resolution targets win_amd64, so you can pack from a non-Windows host when:

  • the project is pure Python, or
  • any native extensions are already buildable as Windows wheels

uvpacker does not cross-compile your own C extensions; use Windows for those projects.

If your project package itself contains native binaries such as .pyd / .dll, the current in-memory embedding mode is not supported and the build will fail. Third-party native dependencies can still remain in packages/.

Packing pipeline

  1. Read and validate pyproject.toml (scripts, gui-scripts, build-system, requires-python)
  2. Resolve Python version and obtain python-<version>-embed-amd64.zip (downloaded once, then cached under ~/.cache/uvpacker/embed, or $XDG_CACHE_HOME/uvpacker/embed if set)
  3. Build a wheel for the target project
  4. uv pip install into packages/ with --python-platform x86_64-pc-windows-msvc
  5. Remove host-style script shims from packages/bin / packages/Scripts
  6. Patch embedded runtime _pth to include ..\packages
  7. For your package tree: compile .py.pyc with the target minor via uv run, then remove .py (light obfuscation; not encryption)
  8. Bundle your project package into an in-memory zip archive, append it to each generated launcher .exe, and remove the duplicated project package / project .dist-info from packages/
  9. Generate .exe launchers (console.exe / gui.exe templates, or skip if missing)

Resource embedding

Runtime follows your wheel’s install layout: uvpacker puts third-party deps in packages/ and imports your package from an archive embedded in each .exe, so you normally do not have a dev tree like src/... beside the executable.

Ship every asset you open with importlib.resources.files inside importable subpackages (e.g. files("myproject.static") for files under myproject/static/ in the wheel). Pass the real dotted package name; do not use .exe-relative paths, bare name guesswork, or Path(__file__).parent / ....

files() often returns a Traversable, not a full pathlib.Path—especially under embedding. Avoid path / "x" and multi-arg joinpath; chain instead: root.joinpath("a").joinpath("b").

Notes

  • Your project package is imported from inside each launcher .exe, not from packages/.
  • packages/ is reserved for third-party dependencies needed at runtime.
  • The project's own .dist-info metadata is removed from packages/ after embedding.
  • Bundled project files: use importlib.resources as described under Resource embedding.

License

GNU General Public License v3.0 — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

uvpacker-0.5.2.tar.gz (60.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

uvpacker-0.5.2-py3-none-any.whl (60.5 kB view details)

Uploaded Python 3

File details

Details for the file uvpacker-0.5.2.tar.gz.

File metadata

  • Download URL: uvpacker-0.5.2.tar.gz
  • Upload date:
  • Size: 60.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for uvpacker-0.5.2.tar.gz
Algorithm Hash digest
SHA256 22211c6caa64188f90cc9de74af0bb63f3d9d62e4e85db8adb73f8651c061dbb
MD5 511b7604a106c93fdea60a611cb7d273
BLAKE2b-256 59df1e2e85a7fd2ece0cdf3db1ffeb7ea8868f4cd74d3f410df221e22f2d49bb

See more details on using hashes here.

Provenance

The following attestation bundles were made for uvpacker-0.5.2.tar.gz:

Publisher: publish.yml on touken928/uvpacker

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file uvpacker-0.5.2-py3-none-any.whl.

File metadata

  • Download URL: uvpacker-0.5.2-py3-none-any.whl
  • Upload date:
  • Size: 60.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for uvpacker-0.5.2-py3-none-any.whl
Algorithm Hash digest
SHA256 04f85d430b8fc7a6d62a37c68ce199de15d87314ced95411c4c18e4dc47c4430
MD5 476deb052316b5e9227da0aa1dcb5541
BLAKE2b-256 1c74319d9184bccb430363795e2c4ee97497b2b2c747609949dce4de7942a9ca

See more details on using hashes here.

Provenance

The following attestation bundles were made for uvpacker-0.5.2-py3-none-any.whl:

Publisher: publish.yml on touken928/uvpacker

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page