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.6.0.tar.gz (64.8 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.6.0-py3-none-any.whl (69.5 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for uvpacker-0.6.0.tar.gz
Algorithm Hash digest
SHA256 f666ddf88e4e68feed9d4b49e9fcfe982f81c3d7ec047a2c83433d56e8690795
MD5 e35f3defbefc767bce48ec70f18b2dbb
BLAKE2b-256 99acff46e7cd25d8ced0bd4c1931a0ab7bf8df2838fa36b1e98723fa102809a0

See more details on using hashes here.

Provenance

The following attestation bundles were made for uvpacker-0.6.0.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.6.0-py3-none-any.whl.

File metadata

  • Download URL: uvpacker-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 69.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.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d070fcec7538315b8ffcc4b94c75d37f4aaf4014f570ff84eaa7682097575187
MD5 bb922676823f85bca317a44020cba7e3
BLAKE2b-256 1266cb80faf224df5dfb39b2829281c030cca7291a0fde50aabebac42ff24783

See more details on using hashes here.

Provenance

The following attestation bundles were made for uvpacker-0.6.0-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