Solutions to the Common Issues

We recommend this page if you find Nuitka is not working out of the box for you. There are typical issues encountered and their solutions.

This page can also teach you more about Nuitka advanced concepts; therefore, we recommend reading it for all levels of Nuitka users. It helps a lot to avoid issues and avoid non-optimal results.

Deployment Mode

The non-deployment mode of Nuitka intends to assist you at the runtime of the compiled program. It aims to give you better error information and to catch typical user errors.

By default, Nuitka is set to compile in non-deployment mode, which can be deactivated using the --deployment option. In this mode, Nuitka activates a range of safety guards and helpers to identify and resolve any incorrect usage of Nuitka.

If you want to disable all these helpers, read more in the Disabling All section. Following is the list of currently implemented helpers you can also deactivate individually by name, and you might have to.

Fork Bombs (Self-execution)

So after compilation, sys.executable is the compiled binary. Certain Python packages like multiprocessing, joblib, or loky typically expect to run from a full Python environment with sys.executable. They expect to use the -c command or -m module_name options to be able to launch other code temporarily or permanently as a service daemon.

However, with Nuitka, this executes your program again and puts these arguments in sys.argv where you maybe ignore them, and then you fork yourself again to launch the helper daemons. That leads to unintentionally repeated forking, potentially resulting in a scenario called fork bomb, where multiple processes spawn recursively, causing system freeze.

For example, running a program compiled with Nuitka may trigger the following error:

./hello.dist/hello.bin -l fooL -m fooM -n fooN -o fooO -p
Error, the program tried to call itself with '-m' argument. Disable with '--no-deployment-flag=self-execution'.

To avoid this issue, ensure your program handles command line parsing correctly and avoids using unsupported packages that attempt re-execution. Additionally, you can turn off this specific behavior at compile time by using the --no-deployment-flag=self-execution flag.

Misleading Messages

Some Python packages generate misleading error messages when they encounter import failures. These messages sometimes suggest actions that may not be the appropriate solution for compiled programs. Nuitka tries to correct them in non-deployment mode. Here is an example where Nuitka changes a message that asks to pip install ... a package. That, of course, is not the issue, and instead, Nuitka makes the program point the user to the --include-module option to use. With that, the imageio plugin will work.

- module-name: 'imageio.core.imopen'
  anti-bloat:
    - replacements_plain:
        '`pip install imageio[{config.install_name}]` to install it': '`--include-module={config.module_name}` with Nuitka to include it'
        'err_type = ImportError': 'err_type = RuntimeError'
      when: 'not deployment'

And much more

The non-deployment mode of Nuitka is constantly evolving and adding more features, for example, something for FileNotFoundError should be added; there are plenty of ideas.

Disabling All

Of course, all these helpers are removed at once when using the --deployment option of Nuitka, but remember that you may want to re-enable it for debugging. To make this easy to toggle, you should use Nuitka Project Options and check an environment variable in them.

# nuitka-project-if: os.getenv("DEPLOYMENT") == "yes":
#  nuitka-project: --deployment

Why should you not disable them all during development?

We recommend selective disabling, as with PyPI upgrades and your code changes, these issues can resurface. The space saved by deployment mode is minimal, so we advise not to disable them. Instead, review each feature, and if you know, it won’t affect your software or you won’t need it, turn it off.

Windows Virus Scanners

Some Antivirus Vendors may flag compile binaries using Nuitka’s default settings on Windows as malware. That happens a lot if you compile without additional steps. You can avoid this by purchasing the Nuitka Commercial plan and following the instructions given. You can solve it with those instructions and support, but there are no guarantees.

Linux Standalone

For Linux standalone, building a binary that works on older Linux versions is challenging. Because on Linux, distributors build Python software to link against the concrete system explicitly DLLs. As a consequence, it often does not run on other Linux flavors.

The solution is to compile your application on the oldest Linux version that you intend to support. However, this process can be exhausting, involving setup complexities and security considerations since it exposes source code.

We recommend purchasing Nuitka Commercial plan to overcome this issue without extra effort. Nuitka Commercial has container-based builds that you can use. This container uses dedicated optimized Python builds, targeting CentOS 7 and supporting even the newest Pythons and old operating systems. This solution streamlines the process by integrating recent C compiler chains.

Program Crashes System (Fork Bombs)

A fork bomb is a program that spawns recursively, causing a system lock and ultimately crashing it in short order. That happens since sys.executable for a compiled program is not the Python interpreter it usually is, and packages that try to do multiprocessing in a better way relaunch themselves. That starts the process all over again unless taken care of.

Nuitka handles it for all packages known to do that; for example, joblib. However, you may encounter a situation where the detection of this fails. To turn off this protection, read about the Fork Bombs (Self-execution) option.

To debug fork bombs, use the --experimental=debug-self-forking option to check program fork behavior. To minimize risks associated with fork bombs, put the following code snippet at the very beginning of your program.

import os, sys

if "NUITKA_LAUNCH_TOKEN" in os.environ:
   sys.exit("Error, launch token must not be present or else fork bomb suspected.")
os.environ["NUITKA_LAUNCH_TOKEN"] = "1"

This code checks for the presence of the environment variable NUITKA_LAUNCH_TOKEN and the program reacts with an error exit. Otherwise, it sets the NUITKA_LAUNCH_TOKEN in the environment, so afterward, the potential fork bomb is detected, should the program re-execute itself.

Nuitka handles fork bombs without the deployment option if it finds -c and -m options, as typically used with the Python interpreter to execute code. However, the detection may need improvement to work well, with a new package (or a previously working package in a newer version).

Memory issues and compiler bugs

Sometimes, the C compilers will crash with unspecific errors. It may be saying they cannot allocate memory, that some assembly input was truncated, or other similar error messages. All of these can be caused by using more memory than is available.

These are example error messages that are a sure sign of memory being too low; there is no end to them.

# gcc
fatal error: error writing to -: Invalid argument
Killed signal terminated program
{standard input}: Assembler messages:
{standard input}: Warning: end of file not at end of a line; newline inserted
# MSVC
fatal error C1002: compiler is out of heap space in pass 2
fatal error C1001: Internal compiler error

There are several approaches you can explore here.

Ask Nuitka to use less memory

There is a dedicated option --low-memory which influences decisions of Nuitka, such that it avoids high usage of memory during compilation at the cost of increased compile time.

Avoid 32-bit C compiler/assembler memory limits

Do not use a 32-bit compiler, but a 64-bit one. If you use Python with 32 bits on Windows, you should use MSVC as the C compiler, not MinGW64. The MSVC is a cross-compiler and can use more memory than MinGW64 on that platform. Also, using the 64-bit Python will work.

Use a minimal virtualenv

When you compile from an installation used for many packages and programs, you may have many optional dependencies of your software installed. Some software will then have imports on these, and Nuitka will compile them as well. Not only may these be just the troublemakers, but they also require more memory, so get rid of that. Of course, you do have to check that your program has all the needed dependencies before you attempt to compile, or else the compiled program will equally not run.

Use LTO compilation or not

Link time optimization (LTO) is a technique modern compilers allow for. With --lto=yes or --lto=no, you can switch the C compilation to only produce bytecode, and not assembler code and machine code directly, but make a whole program optimization at the end.

Using LTO will change memory usage dramatically, and if your error is coming from the assembler, using LTO will most likely avoid that. On the other hand, LTO does much more work during linking and can itself be the cause of the memory shortage.

There is no clear answer to whether ** LTO ** or not is better for memory usage, but you can attempt switching.

Switch the C compiler to Clang

Some Nuitka users have reported that programs that fail to compile with GCC due to its bugs or memory usage work fine with Clang on Linux. On Windows, since MSVC is known to be more memory effective, you should go there first. But adding the option --clang to your compilation may help you.

Add a larger swap file to your embedded Linux

On systems with not enough RAM, you need to use swap space. Running out of it is possibly a cause, and adding more swap space, or one at all, might solve the issue, but beware that it will make things extremely slow when the compilers swap back and forth, so consider the following tip first or on top of it.

Refer to your systems instructions on how to add swap space to a Linux installation.

Limit the number of compilation jobs

With the --jobs option of Nuitka, it will not start many C compiler instances at once, each competing for the scarce resource of RAM. For example, picking a value of 1 on an eight-core system reduces the amount of memory by a factor up to 8.

Note

The --low-memory option implies --jobs=1 already.

Dynamic sys.path at runtime

If your program (or some used modules) modify sys.path at runtime, for example, inserting directories with source code relative to it, Nuitka will not be able to see those. However, if you set the PYTHONPATH to the resulting value, Nuitka will be able to locate the modules used from there as well.

Manual Python File Loading

A widespread pattern with private code is that it scans plugin directories of some kind, and for example, uses os.listdir, then considers Python filenames, and then opens a file and does exec on them.

This approach only works for Python source code but for compiled code, you should use this much cleaner approach that works for pure Python code and is a lot less vulnerable.

# Using a package name to locate the plugins. Also, a good approach
# way to organize them into a directory.
scan_path = scan_package.__path__

for item in pkgutil.iter_modules(scan_path):
   importlib.import_module(scan_package.__name__ + "." + item.name)

   # You may want to do it recursively, but we don't do this here in
   # this example. If you'd like to, handle that in this kind of branch.
   if item.ispkg:
      ...

Missing data files in standalone

If your program fails to find a data file, it can cause different problematic behavior; for example, a package might complain that it is not the correct version because a VERSION read from the file usually was not found, and instead, it uses a default value. The absence of files containing, for example, icons may cause visual issues only or databases, or texts missing in a file, which may also raise all kinds of strange errors.

Often, the error handling code paths for files that are not present are even buggy and will reveal programming errors like unbound local variables. Please look carefully at these exceptions, considering this can be the cause. If your program works fails --mode=standalone and works only with --follow-imports, data files are likely the cause.

The most common error indicating file absence is, of course, an uncaught FileNotFoundError with a filename. You should figure out what the Python package is that is missing files and then use --include-package-data (preferably), or --include-data-dir/--include-data-files to include them.

You can read all about data files in Data Files; there are much more detail to learn than is covered here.

Missing DLLs/EXEs in standalone

Nuitka has plugins and configurations to deal with copying DLLs needed by some packages. It covers NumPy, SciPy, Tkinter, and practically all popular packages.

The DLLs need special treatment to be able to run on other systems, merely copying them is not working and will give strange errors at runtime.

Sometimes, newer versions of packages, such as NumPy, can be unsupported. In this situation, you will have to raise an issue so we can also add support for it.

If you want to manually add a DLL or an EXE because it is your project only, you must use user Yaml files to describe their location.

The reference for the syntax to use with examples is in the Nuitka Package Configuration page.

Dependency creep in standalone

Some packages are a single import, but to Nuitka means that more than a thousand packages (literally) are included as its dependency. One example is IPython, which does want to plug and use just about everything you can imagine. Multiple frameworks for syntax highlighting everything imaginable take time.

Nuitka will have to learn effective caching to deal with this in the future. Presently, you will have to deal with substantial compilation times for these.

A major weapon in fighting dependency creep should be applied, namely the anti-bloat plugin, which offers interesting abilities that can be put to use and block unneeded imports, giving an error for where they occur. Use it for example like this --noinclude-pytest-mode=nofollow --noinclude-setuptools-mode=nofollow and, for example, also --noinclude-custom-mode=setuptools:error to get the compiler to error out for a specific package. Make sure to check its help output. It can take for each module of your choice, for example, forcing also that for example PyQt5 is considered uninstalled for standalone mode.

A configuration file drives it, standard.nuitka-package.config.yml that you can contribute to, removing typical bloat from packages. Please join us in enhancing it and making PRs towards Nuitka for more and more packages to compile without severe bloat.

Standalone: Finding files

The standard code that normally works also works; you should refer to os.path.dirname(__file__) or use all the packages like pkgutil, pkg_resources, importlib.resources to locate data files near the standalone binary.

Important

What you should not do is use the current directory os.getcwd, or assume that . is the script directory for example with paths like data/.

If you did that, it was never good code. Links to a program, launching it from another directory, or code changing the current directory will all cause failures. Do not make assumptions about the directory from which your program starts.

Tip

Want to catch these errors before compiling?

Using the terminal, create a sub-directory, move one directory up, and then run your program like this python ../main.py and correct all the errors you will encounter compared to python main.py.

It goes a long way to not having issues after compilation in standalone mode to do this, but make sure to refer to os.path.dirname(__file__) for files to be part of your compiled program installation, and for files that are to reside next to the compiled program use os.path.dirname(sys.argv[0]).

In case you mean to refer to the location of the .dist folder for files that are to reside near the binary, there is __compiled__.containing_dir that also abstracts all differences with --macos-create-app-bundle and the .app folder a having more nested structure.

# This will find a file *near* your app or dist folder
try:
   open(os.path.join(__compiled__.containing_dir, "user-provided-file.txt"))
except NameError:
   open(os.path.join(os.path.dirname(sys.argv[0]), "user-provided-file.txt"))

Onefile: Finding files

There is a difference between sys.argv[0] and __file__ of the main module for the onefile mode, which is caused by using a bootstrap to a temporary location. The first will be the original executable path, whereas the second will be the temporary or permanent path the bootstrap executable unpacks to. Data files will be in the later location; your original environment files will be in the former location.

Given two files, one which you expect to be near your executable and one which you expect to be inside the onefile binary, access them like this.

# This will find a file *near* your onefile.exe
open(os.path.join(os.path.dirname(sys.argv[0]), "user-provided-file.txt"))
# This will find a file *inside* your onefile.exe
open(os.path.join(os.path.dirname(__file__), "user-provided-file.txt"))

# This will find a file *near* your onefile binary and work for standalone too
try:
   open(os.path.join(__compiled__.containing_dir, "user-provided-file.txt"))
except NameError:
   open(os.path.join(os.path.dirname(sys.argv[0]), "user-provided-file.txt"))

Windows Programs with no console give no errors

For debugging purposes, remove --disable-console or use the options --force-stdout-spec and --force-stderr-spec with paths as documented for --onefile-tempdir-spec above. These can be program relative, absolute paths, or temp directories.

Example

You may, for example, use --force-stdout-spec={PROGRAM_BASE}.out.txt and --force-stderr-spec={PROGRAM_BASE}.err.txt and use Nuitka Project Options to enable them with environment variables in your compilation.

# nuitka-project-if: os.getenv("DEBUG") == "yes":
#  nuitka-project: --force-stdout-spec={PROGRAM_BASE}.out.txt
#  nuitka-project: --force-stderr-spec={PROGRAM_BASE}.err.txt

Use these options to capture the errors and outputs and check them; they will contain Python tracebacks and, generally, the information you would use to debug your program.

Deep copying uncompiled functions

Sometimes, people use this kind of code, which we deal with for packages on PyPI by doing source code patches on the fly. If this is in your code, here is what you can do:

def binder(func, name):
   result = types.FunctionType(func.__code__, func.__globals__, name=func.__name__, argdefs=func.__defaults__, closure=func.__closure__)
   result = functools.update_wrapper(result, func)
   result.__kwdefaults__ = func.__kwdefaults__
   result.__name__ = name
   return result

Code cannot use compiled functions to create uncompiled ones from them, so the above code will not work. However, there is a dedicated clone method that is specific to them, so use this instead.

def binder(func, name):
   try:
      result = func.clone()
   except AttributeError:
      result = types.FunctionType(func.__code__, func.__globals__, name=func.__name__, argdefs=func.__defaults__, closure=func.__closure__)
      result = functools.update_wrapper(result, func)
      result.__kwdefaults__ = func.__kwdefaults__

   result.__name__ = name
   return result

Modules: Extension modules are not executable directly

You can compile modules and packages with Nuitka, no problem, but when it comes to executing it, python -m compiled_module is not going to work and give the error No code object available for <module_name>.

Because the compiled module is not source code, and Python will not just load it with the -m implementation. The closest to it is python -c "import compile_module" and you might have to call the main function yourself.

To support this, the Python runpy and/or ExtensionFileLoader would need improving such that Nuitka could supply its compiled module object for Python to use.