Nuitka vs pyinstaller: compiling your modules against freezing an interpreter
Both hand a user a program that starts without a Python installation, but they get there by different routes. Nuitka translates your modules into a C level program that links against libpython, so it is a compiler with packaging modes attached. pyinstaller analyses your script, collects copies of every module it needs including the active interpreter, and puts them in a folder or a single file, so it is a bundler. Choose Nuitka when you want your code compiled and a C toolchain on the build machine, and pyinstaller when you want the interpreter shipped with the app.
At a glance
| Project | Nuitka/Nuitka | pyinstaller/pyinstaller |
|---|---|---|
| Licence | AGPL-3.0Network copyleft: hosting a modified version means sharing source | Custom licenceCustom licence: read the LICENSE file |
| Maintenance | Commits in the last six monthsLast push November 6, 2026 | Commits in the last six monthsLast push November 6, 2026 |
| Language | Python | Python |
| GitHub stars | 15,225 | 13,142 |
| Read more | Our analysisGitHub | Our analysisGitHub |
Star history
- Nuitka/Nuitka15,225 ★ · +82
- pyinstaller/pyinstaller13,142 ★ · +40
| Repository | 2026-09-22 | 2026-11-07 |
|---|---|---|
| Nuitka/Nuitka | 15.1k | 15.2k |
| pyinstaller/pyinstaller | 13.1k | 13.1k |
Which one to choose
Choose Nuitka if you ship a CPython program to machines that have no Python and you control the build machine's C compiler. It compiles every construct of the Python version it runs under, links against libpython, offers --mode=standalone and --mode=onefile so the binary runs without a Python installation, and works as an extension module as well as an executable. Choose it when the code being compiled matters to you, when you can meet the AGPL-3.0 obligations with its runtime exception, and when your target is not Windows app store Python, macOS pyenv, or MinGW64 with Python 3.13 or above.
Choose pyinstaller if you need a working application on a machine you do not control, and you would rather not manage a C compiler. It bundles numpy, PyQt5, PySide2, PyQt6, PySide6, wxPython and matplotlib out of the box, supports code signing on macOS and bundles MS Visual C++ DLLs on Windows, supports Python 3.8 to 3.15, and is a single command against your main script. Choose it for desktop distribution where the priority is that it starts, and build on each target platform because it is not a cross-compiler.
Compiling your modules against freezing an interpreter
Nuitka calls itself the Python compiler, and the manual explains the mechanism in plain terms. You give it a Python application, and it translates the Python modules into a C level program that then uses libpython and static C files of its own to execute in the same way as CPython does. It compiles every construct that Python 2.6, 2.7 and Python 3.4 to 3.14 have, when it is itself run with that Python version, and it then executes uncompiled code and compiled code together. The manual is careful about what the optimisation is for: all of it is aimed at avoiding overhead where the overhead is unnecessary, and none of it is aimed at removing compatibility, with occasional improvements such as more complete error messages and a full compatibility mode to disable even those. The output is an executable or an extension module.
pyinstaller describes a different process in the same plain terms. It reads a Python script written by you, analyses your code to discover every other module and library the script needs, then collects copies of all those files, including the active Python interpreter, and puts them with your script in a single folder or optionally in a single executable file. The result is a package rather than a compiled program: your code is still Python, and the reason it runs anywhere is that a copy of the interpreter and every dependency is travelling with it.
That difference explains almost every practical consequence. Compiling means a C compiler, a build step that can fail on a machine you control, and output that still reaches libpython at run time. Freezing means no compiler on the build machine, a bundle that includes Python, and output that carries the interpreter's size and its compatibility range into every copy you ship.
Build machines, compilers and what each one asks of you
Nuitka's requirements are stated in detail because they have to be. You need a C compiler with C11 support, or alternatively a C++ compiler for C++03, and the manual names the accepted ones. On Windows that is Visual Studio 2022 or higher, with an English language pack because Nuitka filters away garbage output only for English, the MinGW64 C11 compiler used with --mingw64 which Nuitka downloads automatically if no usable compiler is found, the zig compiler with --zig which on Windows is currently limited to compiling for x64 Python, and clang-cl if the Visual Studio installer provides it. On other platforms it is gcc of at least version 5.1, g++ of at least 4.4 as an alternative, and clang on macOS and most FreeBSD architectures. The manual also notes that the older MSVC compilers do not support C11 yet, and that with Python 3.10 or older it falls back to C++03 as a workaround. Our analysis puts the same requirement in one line: you must be able to control the build machine's C compiler.
pyinstaller asks for a compiler only on platforms nobody tests. It is tested against Windows, macOS and GNU/Linux, and for any contributed platform such as FreeBSD, Solaris, AIX or another libc and architecture combination, the manual says you need to build the PyInstaller bootloader, which happens automatically when you pip install pyinstaller provided an appropriate C compiler, typically gcc or clang, and zlib's development headers are already installed. On the tested platforms there is no compiler step at all: pip install pyinstaller, then pyinstaller /path/to/yourscript.py.
The Linux requirements are worth reading whichever tool you pick, because they describe the build host rather than the target. pyinstaller lists GNU libc based distributions on x86_64, aarch64, i686, ppc64le and s390x, musl libc based distributions on x86_64 and aarch64, and the console tools ldd, objdump and objcopy, with piwheels as an extra index URL for Raspberry Pi users on armv5 to armv7.
Interpreter versions and the packaging modes
Version support is where the two diverge most visibly. Nuitka's manual states that Python 2.6, 2.7 and Python 3.4 to 3.14 are supported, that if a stable Python release is not in the list it is being worked on, and that Nuitka itself is compatible with all listed versions while Scons, the tool it uses internally, is not. For Python 3.4 and only that version another Python is needed at compile time. There is also a hard constraint on the interpreter implementation itself: the manual has an admonition stating that it has to be CPython, Anaconda Python or Homebrew Python, and that you need the standard implementation to execute Nuitka because it is closely tied to implementation details. Our analysis makes the same point in its pre-commit checklist.
pyinstaller supports Python 3.8 to 3.15, works out of the box with any of them, and calls out two exceptions: Python 3.10.0 contains a bug that makes it unsupportable, and it does not work with beta releases of Python 3.16. On Windows it should work on Windows 7 or newer while officially supporting Windows 8+, and support for Python installed from the Windows Store without a virtual environment requires PyInstaller 4.4 or later. On macOS it needs 10.15 Catalina or newer, and universal2 applications are supported provided your Python installation and all your dependencies are also universal2.
The packaging modes are Nuitka's side of the story. The manual states that the created binaries can be made executable independent of the Python installation with --mode=standalone and --mode=onefile, and it names the filename behaviour: an .exe suffix on Windows, no suffix for standalone mode on other platforms or a .bin suffix you are free to remove or change, with -o to specify. pyinstaller's equivalent choice is between a folder and a single executable file, and its one-file mode exists so the user needs no installation step at all.
What ends up in the artefact and how it runs
The bundle is the difference you can measure. A pyinstaller artefact contains copies of your script, every module the analysis found, every dependency, and the active Python interpreter, which the README lists as a headline advantage: it fully multi-platform, uses OS support to load the dynamic libraries, and correctly bundles the major packages including numpy, PyQt5, PySide2, PyQt6, PySide6, wxPython and matplotlib, with the tricks needed to make external packages work already integrated. It also works with code signing on macOS and bundles MS Visual C++ DLLs on Windows. The cost is that every copy carries a Python runtime and that the supported interpreter range travels with the file.
A Nuitka artefact is a compiled program that still needs Python at run time, unless you choose standalone or onefile mode, which bundle the runtime for you. The manual is explicit that all Python library modules and extension modules can be used freely, and the compiled and uncompiled code runs together, so the compatibility surface is the one you already have. The output is a program rather than a folder, and the manual explains that the acceleration mode adds a suffix only so the original script name and the binary name cannot collide, letting the binary overwrite safely without destroying the source.
For a desktop application with a GUI toolkit, the practical question is whether your dependency tree is covered. Our analysis says to confirm that every third-party package in your dependency tree is covered by pyinstaller-hooks-contrib for your target platform, and pyinstaller's own list of major packages bundled out of the box is the short version of that answer. For Nuitka, the equivalent risk is different: a C extension module that has not been seen by the compiler is a build failure, and the manual's promise that extension modules can be used freely is a promise about the mechanism rather than a list of verified packages.
Where Nuitka falls short
It is not a faster interpreter, and the project says so. Our analysis describes it as a packaging and acceleration tool for people who need a binary, not a faster interpreter, and tells you not to adopt it expecting a drop-in speedup. The manual's own framing agrees: optimisation is aimed at avoiding unnecessary overhead, not at removing compatibility, and the occasional improvement is a better error message you can switch off.
The build requirements are the real tax. A C compiler with C11, or Visual Studio 2022 with an English language pack on Windows, or gcc 5.1 or clang elsewhere, plus Scons, plus in some configurations a second Python at compile time and a MinGW64 download that Nuitka fetches for you. Every one of those is a thing that can be missing, be the wrong version, or behave differently on a build agent than on a developer machine.
There are named exclusions. The manual states that MinGW64 does not work with Python 3.13 or higher, that the zig compiler on Windows is currently limited to x64 Python, and that on Windows Python2 cannot be used for the compile-time dependency because clcache does not work with it. Our analysis adds the deployment-side exclusions: do not adopt it if your target is Windows app store Python, macOS pyenv, or MinGW64 on Python 3.13 and above. And the interpreter itself must be CPython, Anaconda or Homebrew, which rules out some environments a team might otherwise reach for.
The version line is also wide in a way that matters: 2.6, 2.7 and 3.4 through 3.14, with 3.4 needing a different Python at compile time. Supporting a version that old is a maintenance surface on the project, and it means the manual is the page you read rather than a short command reference.
Where pyinstaller falls short
It is not a compiler. Our analysis is explicit that you should not adopt it if your real requirement is compiling Python to native code for speed, and the mechanism explains why: the bundle contains a copy of the interpreter, so the code still runs on CPython, just a private one.
It is not a cross-compiler, and the README states that plainly: to make a Windows app you run PyInstaller in Windows, to make a GNU/Linux app you run it in GNU/Linux. Our analysis says that constraint shapes every workflow built on it, and tells you not to adopt it if you need to build a Windows binary from a Linux CI runner. A release pipeline that produces per-platform artefacts therefore needs per-platform runners, which is a cost in infrastructure rather than in code.
The dependency surface is decided by an analysis step. PyInstaller reads your script and infers what it needs, and the README's claim that all the required tricks to make external packages work are already integrated is a claim about the hooks rather than about every package that exists. Our analysis tells you to confirm coverage for your target platform, and packages that load plugins at run time, or that shell out to a system tool, or that read data files by path, are the ones where a static analysis is least likely to be right.
There are version and platform edges. Python 3.10.0 is unsupportable, beta releases of Python 3.16 do not work, Windows 7 is expected to work but only Windows 8 and newer is officially supported, and macOS needs 10.15 or newer with universal2 only when your Python and dependencies are universal2 too. Platforms outside the tested set, which include FreeBSD, Solaris, AIX and other libc and architecture combinations, are untested by the project's continuous integration and require you to build the bootloader yourself.
Licence, maintenance and the choice for concrete situations
The licences need reading on both sides, for different reasons. Nuitka is AGPL-3.0, and our analysis tells you to confirm that your distribution obligations under AGPL-3.0 with the runtime exception are acceptable to whoever reviews licences, which is a different conversation from the one a permissive licence avoids. pyinstaller is listed under a custom licence that GitHub cannot classify, with the LICENSE file named as the place where the terms are, so the badge tells you nothing and the file tells you everything. Neither tool lets you skip the reading step.
Maintenance is close. Nuitka's last recorded push is 2026-09-25 and pyinstaller's is 2026-09-28, neither repository is archived, and both are being worked on. The visible difference is how versions arrive: pyinstaller publishes releases, with v6.22.1 on 2026-08-15, v6.22.2 on 2026-08-17 and v6.22.3 on 2026-09-12, while Nuitka's repository has no GitHub releases and its versioned presence is on PyPI, with the project publishing its manual as a single continuously updated document instead of a per-release changelog. A team that pins a build wants a version artefact, and that is easier on the pyinstaller side.
The situations below are clear.
A desktop application for Windows, macOS or Linux built in CI, one artefact per platform. pyinstaller, with per-platform runners, since it is not a cross-compiler.
An application whose dependencies include numpy, Qt or matplotlib and that must work on a machine with nothing installed. pyinstaller, because those packages are listed as bundled out of the box, and the interpreter travels with the app.
A tool you ship as a single file to users who will never run pip. pyinstaller, and its one-file mode is the reason.
A program you want compiled, with a C toolchain you control on the build machine. Nuitka, because it produces a C level program and an extension module, not a bundle.
A library you want importable as a compiled extension. Nuitka, since an extension module is one of its two documented outputs.
A macOS build with code signing. pyinstaller, which lists code signing support as an advantage; Nuitka's manual is about the compiler and the modes rather than about signing.
A Windows build on Python 3.13 or above with MinGW64, or a target on Windows app store Python or macOS pyenv. Neither, on the evidence in these two projects' own requirements.
Before committing, run the checks each project names. For Nuitka, confirm your interpreter is CPython, Anaconda or Homebrew Python, that gcc 5.1 or clang or the Windows equivalent is present, and that the AGPL-3.0 obligations with the runtime exception pass review. For pyinstaller, confirm the interpreter version you build with, given the 3.8 to 3.15 range and the unsupportable 3.10.0, and confirm every third-party package in your tree is covered by pyinstaller-hooks-contrib for your target platform.
Bottom line
Nuitka is the right choice when you want your own code compiled, because it translates your modules to a C level program that links against libpython and offers standalone and onefile modes, and pyinstaller is the right choice when you want the interpreter to travel with the application, because it bundles your script, its dependencies and a copy of Python into a folder or a single file. Neither is a faster interpreter in the way people sometimes expect, and both need their licence read, AGPL-3.0 with a runtime exception on one side and a custom licence on the other. Verify first that your build machine has the C compiler Nuitka requires, that your interpreter is one it accepts, and that your distribution obligations are acceptable, and for pyinstaller that you are on a supported interpreter version and that your dependencies are covered by its hooks, while remembering to build each platform on that platform. The judgement to take away is that this is a packaging decision rather than a performance one, so decide by whether you want a compiled program or a self-contained bundle.
Sources
Was this useful?