Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
Bundling Python apps
Clone this wiki locally
Due to the way Python imports work and due to the way Python packages are installed on Debian and Ubuntu, it is not trivial to create working AppDirs from them.
To find out what Python files a Python app (let's say "SpiderOak") accesses, you can use
strace -eopen -f ./SpiderOak 2>&1 | grep / | grep -v ENOENT | cut -d "\"" -f 2 | sort | uniq > openedfiles
Instead, it is advised that you use workingenv.py, a script that sets up an isolated environment into which you can install your Python app and its dependencies that are not part of the standard library.
pip2 install workingenv python workingenv.py MyNewEnvironment cd MyNewEnvironment/ SITEPY=$(find -name site.py | head -n 1) cat >> $SITEPY.new <<EOF global USER_BASE, USER_SITE, ENABLE_USER_SITE USER_BASE = None USER_SITE = None EOF cat $SITEPY >> $SITEPY.new mv $SITEPY.new $SITEPY source easy_install bin/activate cd src/ # wget ... tar xzf * ; cd * ; python setup.py install # or easy_install *.egg
Then, in your AppRun file, set $PYTHONPATH to point at MyNewEnvironment/lib/python2.6
Please let me know if there is an easier way to bundle Python apps properly.
Miniconda is a version of Python that can run on multiple distributions. It might be a good idea to use that, because it is supposed to be isolated from the Python in the base system (Linux distribution). https://github.com/HelloZeroNet/ZeroBundle/ appears to be using this. Let us know if you try this.
Here is a script that installs FreeCAD using Conda:
For more information, see https://conda-forge.github.io/
It looks like https://conda-forge.github.io/ has grown beyond "just" Python and may evolve into an option to populate any kind of AppDir.
AppImages converted from debs
If you convert a Python application from debs, then you should bundle Python inside the AppImage and make sure it does not load Python modules from the outside by the following trick:
We can do that by modifying
usr/lib/python2.7/sitecustomize.py like this:
import sys,os prefix = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(sys.path)))) sys.path = [ prefix+s for s in sys.path if not s.startswith(prefix) ]
This works because
sys.path contains the directory from which Python was launched.
The usual way that many wrapper libraries search for system libraries is via ctypes own function which on normal systems returns the .so filename. so in the case of VidCutter, for example:
import ctypes.util sofile = ctypes.util.find_library('mpv')
the value of sofile should return as libmpv.so.1 but within the AppDir folder structure, and thus the resulting AppImage, this wouldn't work, returning None. It seems like
ctypes.util.find_library isn't AppImage friendly (only searches outside of, but not inside the AppImage).You can work around it with a simple exception clause hardcoding the lib's filename like so:
sofile = ctypes.util.find_library('mpv') if sofile is None: sofile = 'libmpv.so.1'
Please see https://github.com/ozmartian/vidcutter/issues/12 for more information.
Doing everything in Python
See https://github.com/benoit-pierre/plover/blob/9dc9fd5b2fb29b740eeb40f23d4a0630e8689b77/linux/appimage.sh for an example for how to create everything using Python, including downloading and building Python itself.
- https://notabug.org/themightyglider/Python_and_pygame_AppImage_tutorial - tutorial on how to bundle Python and Pygame applications
- https://notabug.org/themightyglider/Python_and_pygame_AppImage_tutorial/src/master/howto_py_appimage.sh - example on how to bundle Python and Pygame applications
- https://sedimental.org/the_packaging_gradient.html - comparison of different was of packaging Python applications
- https://www.youtube.com/watch?v=iLVNWfPWAC8 - video covering the same material