Developers corner
Python AppImages are built with the python-appimage
utility,
available from PyPI. This utility can also help packaging Python based
applications as AppImages, using an existing Python AppImage and a recipe
folder.
Caution
The python-appimage
utility can only package applications that can be
directly installed with pip
. For more advanced usage, one needs to extract
the Python AppImage and to edit it, e.g. as explained in the Advanced
installation section. Additional details
on this use case are provided below.
Building a Python AppImage
The primary scope of python-appimage
is to relocate an existing Python
installation inside an AppDir, and to build the corresponding AppImage. For
example, the following
python-appimage build local -p $(which python2)
should build an AppImage of your local Python 2 installation, provided that it exists.
Tip
Help on available arguments and options to python-appimage
can be obtained
with the -h
flag. For example, 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 at runtime, on need. Those are appimagetool for
building AppImages, and patchelf in order to edit ELFs runtime paths
(RPATH
). Auxiliary tools are installed to the the user space. One can get
their location with the which
command word. For example,
python-appimage which appimagetool
returns the location of appimagetool
, if it has been installed. If not, the
install
command word can be used in order to trigger its installation.
Manylinux Python AppImages
AppImages of your local python
are unlikely to be portable, except if you run
an ancient Linux distribution. Indeed, a core component preventing portability
across Linuses is the use of different versions of the glibc
system library.
Hopefully, glibc
is highly backward compatible. Therefore, a simple
work-around is to compile binaries using the oldest Linux distro you can afford
to. This is the strategy used for creating portable AppImages, as well as for
distributing 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 various versions of Python already
installed. The python-appimage
utility can be used to package those installs
as AppImages. For example, the following command
python-appimage build manylinux 2014_x86_64 cp310-cp310
should build an AppImage of Python 3.10 using the CPython (cp310-cp310)
install found in the manylinux2014_x86_64
Docker image.
Note
Docker needs to be already installed on your system in order to build Manylinux Python images. However, the command above can be run on the host. That is, you need not to explictly shell inside the manylinux Docker image.
Tip
A compilation of ready-to-use Manylinux Python AppImages is available from
the releases area of the python-appimage
GitHub
repository. These AppImages are updated weekly, on every Sunday.
Simple packaging
The python-appimage
utility can also be used in order to build simple
applications, that can be pip
installed. The syntax is
python-appimage build app -p 3.10 /path/to/recipe/folder
in order to build a Python 3.10 based application from a recipe folder. Examples of recipes can be found on GitHub in the applications folder. The recipe folder contains:
- the AppImage metadata (
application.xml
andapplication.desktop
), - an application icon (e.g.
application.png
), - a Python requirements file (
requirements.txt
) - an entry point script (
entrypoint.sh
).
Additional information on metadata can be found in the AppImage documentation.
That is, for desktop and AppStream XML
files. The requirements.txt
file allows to specify additional site packages
to be bundled in the AppImage, using pip
.
Caution
For the application to be portable, site packages bundled in the AppImage, as well as their dependencies, must must be available as binary wheels, or be pure Python packages.
If a C extension is bundled from source, then it will likely not be portable, as further discussed in the Advanced packaging section.
Tip
Some site packages are available only for specific Manylinux tags. This can
be cross-checked by browsing the Download files
section on the package's
PyPI page.
Tip
Since version 1.2, python-appimage
allows to specify local requirements as
well, using the local+
tag (see
PR49). Note however that
this performs a direct copy of the local package, which has several
limitations.
Entry point script
The entry point script deserves some additional explanations. This script allows
to customize the startup of your application. A typical entrypoint.sh
script
would look like
{{ 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 some
particular variables, nested between double curly braces, {{ }}
. Those
variables are listed in the table hereafter. In addition, usual AppImage
environement variables can be used as well, if needed. For
example, $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 the user space, nor from
Python specific environment variables, the like PYTHONPATH
. Depending on
your use case, this can be problematic.
The runtime isolation level can be changed by adding the -E
, -s
or -I
options, when invoking the runtime. For example,
{{ python-executable }} -I
starts a fully isolated Python instance.
Advanced packaging
In more complex cases, e.g. if your application relies on external C libraries
not bundled with the Python runtime, then the simple packaging scheme described
previously will fail. Indeed, this falls out of the scope of python-appimage
,
whose main purpose it to relocate an existing Python install. In this case, you
might rather refer to the initial AppImage Packaging
Guide, and use alternative tools like
linuxdeploy.
However, python-appimage
can still be of use in more complex cases by
extracting its AppImages to an AppDir, as discussed in the Advanced
installation section. The extracted AppImages
contain a relocatable Python runtime, that can be used as a starting base for
building more complex AppImages.
Tip
In some cases, a simple workaround to missing external libraries can be to
fetch portable versions of those from a Manylinux distro, and to bundle them
under AppDir/usr/lib
. You might also need to edit their dynamic section,
e.g. using patchelf
, which is installed by python-appimage
.
C extension modules
If your application relies on C extension modules, they need to be compiled on a
Manylinux distro in order to be portable. In addition, their dependencies need
to be bundled as well. In this case, you might better start by building a binary
wheel of your package, using tools like Auditwheel which can
automate some parts of the packaging process. Note that auditwheel
is already
installed on the Manylinux Docker images.
Once you have built a binary wheel of your package, it can be used with
python-appimage
in order to package your application as an AppImage.