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.xmlandapplication.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.