Welcome, guest | Sign In | My Account | Store | Cart

This is a handy way to package a group of python modules into a single compressed self-extracting python executable script. This works on UNIX and Cygwin with Python 2.3 Final or later.

Python, 32 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/bin/sh
# This is a self-extracting executable.
# Execute this like any normal executable.
# You may need to "chmod a+x" this file.
# This is a binary ZIP file with a Python loader header.
#
# Bourne shell loader:
PYTHON=$(which python 2>/dev/null)
if [ ! -x "$PYTHON" ] ; then
    echo "Python not found!"
    exit 1
fi
exec $PYTHON -c "
# Python loader:
import sys, os
if int(sys.version[0])<2:
    print 'Python version 2.3 final or greater is required.'
    print 'Your version is', sys.version
    os._exit(1)
major = sys.version_info[0]
minor = sys.version_info[1]
releaselevel = sys.version_info[3]
if (major==2 and minor<3) or (major==2 and minor==3 and releaselevel!='final'):
    print 'Python version 2.3 final or greater is required.'
    print 'Your version is', sys.version
    os._exit(1)
sys.path.insert(0, sys.argv[1])
del sys.argv[0:1]
import MY_SCRIPT
MY_SCRIPT.main()
" $0 $@
# Zip file:

Assume the following situation: * you have a script called MY_SCRIPT.py with a main() function. * your script imports a number of other modules in the local directory. * you want to distribute this script to others as a single executable script that does not require installation or unpacking of all the other modules.

Step 1. Compress your project into a ZIP file:

zip MY_SCRIPT.ZIP *.py

Step 2. Add the shell script header source to the ZIP file. Be sure to change the two references to MY_SCRIPT to the actual name of your script:

cat zip_header.sh MY_SCRIPT.ZIP > SCRIPT

Step 3. Make the SCRIPT executable.

chmod 775 SCRIPT

Step 4. Now run your self-extracting executable ./SCRIPT

This does not corrupt the ZIP file and it is a valid shell script even though it is binary. This is a wrapper, within a wrapper, within a wrapper, but it actually works and it isn't too complicated to build for most projects.

Python is able to run code inside of a ZIP file. The shell script header starts python which runs another pythin script header that loads and run the main function in your script.

2 comments

Vincent Wagelaar 17 years, 7 months ago  # | flag

make if __name__ == '__main__' work. Replace:

sys.path.insert(0, sys.argv[1])
del sys.argv[0:1]
import MY_SCRIPT
MY_SCRIPT.main()

with:

import zipimport #after checking python version
z = zipimport.zipimporter(sys.argv[1])
del sys.argv[0:1]
exec z.get_code('MY_SCRIPT')

After this change a script with the __name__ == '__main__' trick works, no need to specify a main() function.

Anything added beyond. Anything added beyond the script does not get printed to the screen why?

Like is added echo 'Hello'

Which does get printed to the screen

Created by Noah Spurrier on Tue, 29 Aug 2006 (PSF)
Python recipes (4591)
Noah Spurrier's recipes (10)

Required Modules

  • (none specified)

Other Information and Tasks