Skip to content

Bundling Python apps

probonopd edited this page Jan 28, 2017 · 31 revisions

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.

wget http://svn.colorstudy.com/home/ianb/workingenv/workingenv.py
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.

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[0]))))
sys.path = [ prefix+s for s in sys.path if not s.startswith(prefix) ]

This works because sys.path[0] contains the directory from which Python was launched.

References

Also see https://notabug.org/themightyglider/Python_and_pygame_AppImage_tutorial