Skip to content

Repository files navigation

nuitka-minimal

A standalone fastplotlib built with Nuitka. One download, no Python installation, no conda environment. Run your own scripts against it or use the bundled IPython console.

Builds for Linux, macOS and Windows are attached to each release.

Using it

fpl                     # IPython console, fastplotlib imported as fpl
fpl script.py           # run a script
fpl -i script.py        # run a script, then drop into IPython
fpl script.py --arg 1   # arguments after the script go to sys.argv
fpl --console           # console here, never open another terminal

Figures created in the console are ordinary native windows, so fpl.Figure() followed by fig.show() behaves exactly as it does in a normal IPython session.

Launching without a terminal

Started from a file manager or the Dock there is no terminal attached, so the binary opens one and restarts itself inside it.

Windows double-click fpl.exe; Windows opens the console itself
macOS double-click Launch fastplotlib.command
Linux double-click fpl, or run it from a terminal

On Linux this looks for x-terminal-emulator, gnome-terminal, konsole, xfce4-terminal, alacritty, kitty, foot and xterm, in that order. If none of them is installed, run fpl from a terminal yourself.

A script can import anything in the bundle plus its own sibling modules, so a directory of .py files next to each other works the way it normally does:

# analysis/view.py
import tifffile
import fastplotlib as fpl

from preprocess import register   # analysis/preprocess.py

figure = fpl.Figure(shape=(2, 2), size=(900, 700))

for i, path in enumerate(sorted(Path(sys.argv[1]).glob("*.tif"))):
    figure[i // 2, i % 2].add_image(register(tifffile.imread(path)))

figure.show()
fpl.loop.run()
fpl analysis/view.py data/

examples/load_image_series.py is a working version of the above.

What is in the bundle

fastplotlib, pygfx, wgpu, rendercanvas, imgui-bundle, IPython, numpy, scipy, imageio, tifffile, h5py, zarr, scikit-image, pandas. Exact versions are pinned in requirements.txt.

Nothing else can be imported. A Nuitka build compiles a fixed set of modules into the binary; there is no interpreter to pip install into afterwards. If you need another package, add it to requirements.txt and BUNDLED in build.py and rebuild.

Requirements

A working GPU driver on all three platforms. Software rendering does work, but the first draw costs a couple of seconds and it is not interactive.

Linux — glibc 2.35 or newer (Ubuntu 22.04+, Debian 12+, Fedora 36+; not RHEL 9, which is 2.34). Vulkan plus the X11 client libraries:

sudo apt install libvulkan1 mesa-vulkan-drivers \
  libx11-6 libxcursor1 libxi6 libxinerama1 libxrandr2 libxext6 libx11-xcb1

On a Wayland session you also need xwayland; the bundled glfw is the X11 variant.

macOS — 14.0 or newer, Apple Silicon. There is no Intel build: imgui-bundle publishes no x86_64 macOS wheel above 1.3.0, and wgpu ships thin per-architecture dylibs, so universal2 is not available either. Rosetta does not help.

The binary is ad-hoc signed but not notarized, so Gatekeeper blocks it on first launch. Extract with tar -xzf in Terminal rather than Archive Utility, then:

xattr -dr com.apple.quarantine fastplotlib-macos-arm64

Windows — Windows 10 or newer, x64, with a DX12-capable driver. Needs the Visual C++ 2015-2022 redistributable. The binary is unsigned, so SmartScreen shows "Windows protected your PC" — More info then Run anyway. Some antivirus products flag unsigned compiled-Python binaries; verify against the published SHA-256 sums if that happens.

Building

python -m venv ~/venvs/fpl-lite
~/venvs/fpl-lite/bin/pip install -r requirements.txt nuitka==4.1.3
~/venvs/fpl-lite/bin/python build.py

On Linux you also need patchelf. On Windows, MSVC — MinGW does not support Python 3.13. A cold build takes roughly 10 minutes with these dependencies; installing ccache makes rebuilds much faster.

build.py prints the nuitka invocation it runs, then verifies that every file the binary needs at runtime actually landed in the dist. That check is not decoration: Nuitka emits no diagnostic when a data-file pattern matches nothing, so a typo in the package configuration produces a clean build and an artifact that dies on first launch.

Package data

Nuitka discovers pure-Python imports on its own, but not shared libraries opened through ctypes/cffi, data read at import time, or backends reached via importlib.import_module. Rather than accumulating --include-package-data flags until it stops crashing, this repo declares those in fastplotlib.nuitka-package.config.yml, which is the same format Nuitka uses for the packages it supports out of the box (schema).

Two things in there are worth knowing about, because both fail silently:

--include-package-data=wgpu does not include the wgpu native library. Nuitka classifies a .so/.dylib/.dll inside a package as a DLL rather than as package data, and nothing links against this one, so it is never traced:

$ nuitka --list-package-data=wgpu
  wgpu/resources/codegen_report.md
  wgpu/resources/webgpu.h
  wgpu/resources/webgpu.idl
  wgpu/resources/wgpu.h
$ nuitka --list-package-dlls=wgpu
  resources/libwgpu_native-release.so

It needs a dlls: entry. Those two commands are the fastest way to work out what a package actually ships.

wgpu/backends/wgpu_native/_ffi.py imports pip inside a try:, only to build an error hint. Nuitka follows it and compiles all of pip into the binary — about 19 MB. An anti-bloat entry drops it.

Neither wgpu, pygfx, cmap, rendercanvas nor fastplotlib has an entry in Nuitka's shipped configuration. Upstreaming the wgpu and glfw sections would remove the need for this file entirely.

Known issue

Nuitka 4.1.3 miscompiles in-place addition when the left operand is a tuple:

import numpy as np

pos = (0.5, -0.5, 0)
pos += np.array([1.0, 2.0, 3.0])   # CPython: [1.5 1.5 3.]
                                   # Nuitka:  TypeError

Only the in-place form is affected; pos = pos + arr is fine, as is list += arr. This hits fastplotlib/layouts/_plot_area.py in map_screen_to_world, which surfaces as a repeating Draw error: can only concatenate tuple (not "numpy.ndarray") to tuple with a Figure, and as a hard crash for ImageWidget on the offscreen canvas.

About

minimal example that compiles with nuitka

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages