Developers' corner

Python AppImages are created using the python-appimage utility, which is available on PyPI. This utility can also be used to package Python-based applications as AppImages using an existing AppImage and a recipe folder.

Caution

The python-appimage utility can only package applications that can be installed directly with pip. For more advanced usage, it is necessary to extract and edit the Python AppImage, as explained in the Advanced installation section. Further details on this use case can be found below.

Building a Python AppImage

The primary purpose of python-appimage is to relocate an existing Python installation to an AppDir and build the corresponding AppImage. For example, the command

python-appimage build local -p $(which python2)

should create an AppImage of your local Python installation, provided that it exists.

Tip

Help on the available arguments and options for python-appimage can be obtained by using the -h flag. For example, running python-appimage build local -h provides help on local builds.

Auxiliary tools

The python-appimage utility relies on auxiliary tools that are downloaded and installed on demand during application execution. These are appimagetool, which is used to build AppImages, and patchelf, which is used to edit runtime paths (RPATH) in ELF files. These auxiliary tools are installed in the application cache. Their location can be found using the which command. For example, the command

python-appimage which appimagetool

returns the location of appimagetool if it has been installed. If not, the install command can be used to trigger its installation.

Manylinux Python AppImages

AppImages of your local python are unlikely to be portable, unless you are running an outdated Linux distribution. A core component that prevents portability across Linux distributions is the use of different versions of the glibc system library. Fortunately, glibc is highly backward compatible. Therefore, a simple workaround is to compile binaries using the oldest Linux distribution you can. This strategy is used to create portable AppImages and to distribute Python site packages as ready-to-use binary wheels.

The Python Packaging Authority (PyPA) has defined standard platform tags for building Python site packages labelled Manylinux. These build platforms are available as Docker images, with different versions of Python already installed. The python-appimage utility can be used to package these installations as AppImages. For example, the following command

python-appimage build manylinux 2014_x86_64 cp313-cp313

should build an AppImage of Python 3.13 using the CPython (cp313-cp313) installation found in the manylinux2014_x86_64 Docker image.

Note

From version 1.4.0 of python-appimage onwards, Docker is no longer required to build the Manylinux Python images. Cross-building is also supported, for example producing an aarch64 Python image from an x86_64 host.

Warning

Creating multiple Manylinux Python images can significantly increase the size of the application cache. This can be managed using the python-appimage cache command.

Tip

A compilation of ready-to-use Manylinux Python AppImages is available in the releases section of the python-appimage GitHub repository. These AppImages are updated weekly, on every Sunday.

Tip

Instead of an AppImage, the python-appimage build manylinux command can produce either an AppDir or a bare tarball (i.e. without the AppImage layer) of a Manylinux Python installation. See the -b and -n command line options for more information.

Simple packaging

The python-appimage utility can also be used to package simple AppImage applications, whose dependencies can be installed using pip. The syntax is

python-appimage build app -p 3.13 /path/to/recipe/folder

to build a Python 3.13-based application from a recipe folder. Examples of recipes can be found in the applications folder on GitHub. The recipe folder contains

  • the AppImage metadata (application.xml and application.desktop),
  • an application icon (e.g. application.png),
  • a Python requirements file (requirements.txt),
  • an entry point script (entrypoint.sh).

Further information on metadata can be found in the AppImage documentation (e.g., regarding desktop and AppStream XML files). The requirements.txt file enables additional site packages to be specified for bundling in the AppImage using pip.

Caution

In order for the application to be portable, the site packages bundled in the AppImage and their dependencies must be available as binary wheels or pure Python packages.

If a C extension is bundled from source, it will likely not be portable; this is discussed further in the Advanced packaging section.

Tip

Some site packages are only available for specific Manylinux tags. You can check this by browsing the Download files section on the package's PyPI page.

Tip

Since version 1.2, python-appimage allows local requirements to be specified using the local+ tag (see PR49). Please note, however, that this involves directly copying the local package, which has several limitations.

Entry point script

The entry point script deserves some additional explanations. This script lets you customise your application's startup. A typical entrypoint.sh script would look like this

{{ python-executable }} ${APPDIR}/opt/python{{ python-version }}/bin/my_app.py "$@"

where my_app.py is the application startup script installed by pip. As can be seen from the previous example, the entrypoint.sh script recognises particular variables nested between double curly braces ({{}}). These variables are listed in the table below. In addition, the usual AppImage environement variables can be used if needed. For instance, $APPDIR points to the AppImage mount point at runtime.

variable Description
architecture The AppImage architecture, e.g. x86_64.
linux-tag The Manylinux compatibility tag, e.g. manylinux2014_x86_64.
python-executable Path to the AppImage Python runtime.
python-fullversion The Python full version string, e.g. 3.10.2.
python-tag The Python compatibility tag, e.g. cp310-cp310.
python-version The Python short version string, e.g. 3.10.

Note

By default, Python AppImages are not isolated from user space or Python-specific environment variables such as PYTHONPATH. Depending on your use case, this can cause problems.

You can change the isolation level by adding the -E, -s or -I options when invoking the runtime. For example, {{ python-executable }} -I starts a fully isolated Python instance.

Bundling data files

python-appimage is also capable of bundling auxiliary data files directly into the resulting AppImage. The -x/--extra-data switch is used for this purpose. Consider the following example.

echo -n "foo" > foo
mkdir bar
echo -n "baz" > bar/baz
python-appimage [your regular parameters] -x foo bar/*

In this way, user data becomes accessible to the Python code contained within the AppImage as regular files under the directory pointed to by the APPDIR environment variable. An example of a Python 3 script that reads these files is presented below.

import os, pathlib
for fileName in ("foo", "baz"):
  print((pathlib.Path(os.getenv("APPDIR")) / fileName).read_text())

When executed, the above code would produce the following output.

foo
baz

Advanced packaging

In more complex cases, for example if your application relies on external C libraries that are not bundled with the Python runtime, the simple packaging scheme described previously will not work. This falls outside the scope of python-appimage, which is primarily intended for relocating an existing Python installation. In this case, you may wish to refer to the initial AppImage Packaging Guide, and use alternative tools such as linuxdeploy.

However, python-appimage can still be useful in more complex cases, as it can generate a base AppDir containing a relocatable Python runtime (e.g., using the -n option). This can then serve as a starting point to create more complex AppImages.

Tip

In some cases, a simple workaround for missing external libraries is to download portable versions of them from a Manylinux distribution and bundle them in AppDir/usr/lib. You may also need to edit the dynamic section using patchelf, which is installed by python-appimage.

C extension modules

If your application relies on C extension modules, these must be compiled on a Manylinux distribution in order to be portable. Their dependencies also need to be bundled. In this case, it would be better to start by building a binary wheel of your package using tools like Auditwheel, which can automate some parts of the packaging process. Please note that auditwheel is already installed on the Manylinux Docker images.

Once you have built a binary wheel of your package, you can use it with python-appimage to package your application as an AppImage.