Skip to content

PyInstaller

PyInstaller is a Python application bundler that freezes a Python program, the CPython interpreter it was built against, and every imported dependency into a single distributable. The output runs on end-user machines without a pre-installed Python interpreter and without a virtual environment. PyInstaller supports CPython on macOS, Linux, and Windows; there is no iOS, Android, or tvOS target. Install it with uv tool install pyinstaller or pipx install pyinstaller.

Key Features

  • One-folder bundles via --onedir and self-extracting single-file executables via --onefile
  • Hook system that declares hidden imports, data files, and runtime patches for third-party packages
  • Community hook repository (pyinstaller-hooks-contrib) installed alongside PyInstaller, covering packages such as NumPy, SciPy, PyQt, and Matplotlib
  • Spec file workflow for declarative builds (pyinstaller my.spec) in addition to CLI flags
  • --exclude-module flag for trimming unused transitive dependencies out of a bundle
  • Optional UPX compression for smaller executables

Build Process

A PyInstaller spec file orchestrates four stages: Analysis walks the entry-point script’s imports to produce a dependency graph and applies hooks for packages that need special handling. PYZ compiles pure-Python modules to bytecode and packs them into a ZlibArchive. EXE concatenates the PYZ, extension modules, shared libraries, and data files (wrapped internally in a PKG CArchive) onto a precompiled native bootloader and writes the executable. COLLECT copies the executable plus any external dependencies into the output folder for one-folder builds; one-file builds skip COLLECT and emit the self-extracting executable directly.

The bootloader is a small C program that, at runtime, extracts or memory-maps the PYZ archive, initializes the embedded Python interpreter, and executes the frozen entry point. PyInstaller ships precompiled bootloaders for supported platforms; the bootloader source is available in the project repository for teams that need to recompile it.

Distribution Modes

The --onedir mode produces a folder containing the executable, the Python interpreter shared library, and every dependency file. Startup is fast because no archive extraction happens at launch.

The --onefile mode concatenates the same contents into a self-extracting archive. At launch, the bootloader extracts the payload into a temporary directory, runs the program, and cleans up on exit. Startup is slower than --onedir and the temporary directory can be inspected by anyone with filesystem access.

Pros

  • Extensive third-party hook coverage via pyinstaller-hooks-contrib, reducing manual work for packages with C extensions or data files
  • Cross-platform support across macOS, Linux, and Windows from the same spec file
  • Active maintenance with regular releases
  • Licensed GPLv2-or-later with a documented exception that permits distributing bundled applications under any license, including proprietary ones
  • Works with any CPython installation; does not require a specific build backend or project layout

Cons

  • Bundle sizes for ML workloads are large. Community reports for PyTorch and TensorFlow --onefile executables range from roughly 500 MB to 1.5 GB before manual --exclude-module tuning.
  • No built-in code signing. Windows distributions require signtool with a code-signing certificate; macOS distributions require codesign and notarytool with an Apple Developer ID.
  • Antivirus false positives are a known issue. PyInstaller documents rebuilding the bootloader from source and signing the result as a mitigation, which requires a C toolchain on each target platform.
  • --onefile startup is slower than --onedir because the payload is extracted on every launch.
  • No mobile target support. Projects shipping to iOS or Android need a different tool such as Briefcase.
  • Bundles the interpreter at build time, so the build machine’s OS and architecture must match the target. Cross-compilation is not supported.

Alternatives

Nuitka compiles Python source to C and produces a native binary instead of freezing bytecode. cx_Freeze provides a lighter-weight freezing workflow for pure-Python programs without heavy third-party dependencies. Briefcase targets native installer formats and app stores on desktop and mobile platforms.

auto-py-to-exe is a third-party GUI wrapper around PyInstaller. It exposes the PyInstaller CLI flags as form inputs and is maintained independently of PyInstaller itself.

Learn More

Last updated on

Please submit corrections and feedback...