Recipe16.12.Binding Main Script and Modules into One Executable on Unix


Recipe 16.12. Binding Main Script and Modules into One Executable on Unix

Credit: Joerg Raedler

Problem

You have a Python application composed of a main script and some additional modules. You want to bind the script and modules into one executable file, so that no installation procedure is necessary.

Solution

Prepare the following mixed sh/Python script and save it as file zipheader.unix:

#!/bin/sh PYTHON=$(which python 2>/dev/null) if [ x ! -x "x$PYTHON" ] ; then     echo "python executable not found - cannot continue!"     exit 1 fi exec $PYTHON - $0 $@ << END_OF_PYTHON_CODE import sys version = sys.version_info[:2] if version < (2, 3):     print 'Sorry, need Python 2.3 or better; %s.%s is too old!' % version sys.path.insert(0, sys.argv[1]) del sys.argv[0:2] import main main.main( ) END_OF_PYTHON_CODE

Make sure you have the Python bytecode files for the main script of your application (file main.pyc, containing a function named main, which starts the application when called without arguments) and any additional modules your application needs (e.g., files spam.pyc and eggs.pyc). Make a zip file out of them all:

$ zip myapp.zip main.pyc spam.pyc eggs.pyc

(If you prefer, you can build the zip file with an auxiliary Python program, of course.) Next, concatenate the "header" and the zip file, and make the resulting file executable:

$ cat zipheader.unix myapp.zip > myapp $ chmod +x myapp

That's all! Your application is now contained in this executable file myapp. When myapp runs, the shell /bin/sh sets things up and replaces itself with the Python interpreter. The Python interpreter reopens the file as a zip file, skipping the "header" text, and finds all needed modules in the zip file itself.

Discussion

On Windows machines, you would normally use py2exe for similar tasks, as shown previously in Recipe 16.11; on Mac OS X, you would normally use py2app (although this recipe works just as well on Mac OS X as it does on any other Unix).

This recipe is particularly useful for Linux and other Unix variants that come with Python installed. By following the steps outlined in this recipe's Solution, you can distribute a Python application as a single, self-contained standalone executable file, which runs on any version of Unix, on any hardware platformas long as your Python application does not need any C-coded extension modules beyond the ones that come with Python itself. When you do need more, you can use Python's own distutil package to perform more complicated packaging tasks. But for many simple Python applications and quite a few that aren't all that simple, this recipe can be very useful, since it results in a file that can just be run as is, without needing any kind of "installation" step!

The key idea of this recipe is to exploit Python's ability to import modules from a zip file, while skipping leading text that may precede the zip file itself. Here, as leading text, we use a small shell script that turns itself into a Python script, and within the same file continues with the zip file from which everything gets imported. The concept of importing from a zip file is described in Recipe 2.9.

In the zip file, you may, if you wish, place Python source files (with extension .py), as well as compiled bytecode files (with extension .pyc); the latter option is often preferable because if you zip up source files, Python compiles them every time you run the application, slowing your application's startup. On the other hand, if you zip up compiled bytecode files, your application may be unable to run with versions of Python that are newer than the one you used to prepare the bytecode files, since binary compatibility of bytecode files is not guaranteed across Python releases. The best approach may be to place both sources and bytecodes in the zip file.

You may also choose to zip up optimized bytecode files (with extension .pyo)if you do so, you need to add the flag -O right after the $PYTHON in the shell script in this recipe's Solution. Execution speed doesn't generally change much, but optimized execution skips assert statements, which may be important to you. Also, if you prepare the .pyo files by running Python with option -OO, all docstrings are eliminated, which may slightly reduce your application's size on disk (although docstrings tend to compress well, so that size advantage may be minor).

If you need help in finding all the modules that you need to place in the zip file, see the modulefinder module in the Python Standard Library. Unfortunately, no real documentation about it is available at the time of this writing, but just running (in version 2.3) something like:

$ python /usr/lib/python2.3/modulefinder.py main.py

should help (you may have to change the change the path to the modulefinder.py script, depending on your Python installation). With Python 2.4, you can just use the handy new -m switch:

$ python -mmodulefinder main.py

Python 2.4's -m switch lets you run as the main script any module that's on Python's sys.patha very convenient little feature!

See Also

Recipe 16.11; Recipe 2.9; the sources of modules modulefinder and zipimport (which are not yet documented in the Library Reference at the time of writing).



Python Cookbook
Python Cookbook
ISBN: 0596007973
EAN: 2147483647
Year: 2004
Pages: 420

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net