Last Updated: September 09, 2019
·
4.657K
· mehikmat

Making Python zip or tar files executable

Just type the below commands:

$ echo '#!/usr/bin/env python' | cat - your_app_before.zip > your_exec_app

$ chmod +x your_exec_app

5 Responses
Add your response

This is an interesting tip. Where does the interpreter start execution of the scripts in the archive?

over 1 year ago ·

So is the Python interpreter knows how to execute zipped Python code? That's interesting that you can just prepend text to an archive file...

over 1 year ago ·

@chrissimpkins @kazark

There needs to be __main__.py file in inside of zipped file which we need to put before making zip.

Example:

file: __main__.py
import sys
from some_where_else import main
if __name__ == '__main__':
    sys.exit(main())

So python interpreter looks that __main__.py and starts execution.

over 1 year ago ·

Thanks much for sharing this @mehikmat. After a bit of digging, it appears that this was released in Python 2.6.

Here is an approach for Windows from the first comment on the above link (Andy Chu):

On Windows, you can do a similar thing by making a file that is both a zip file and a batch file. The batch file will pass %~f0 (itself) to the -z flag of the Python interpreter.

over 1 year ago ·

This is a hidden gem. Check this out:

~/Desktop/ziptest
▶ ls
__main__.py test.py

~/Desktop/ziptest
▶ zip ziptest.zip __main__.py test.py
  adding: __main__.py (deflated 13%)
  adding: test.py (deflated 21%)

~/Desktop/ziptest
▶ ls
 __main__.py test.py  ziptest.zip

~/Desktop/ziptest
▶ echo '#!/usr/bin/env python' | cat - ziptest.zip > ziptest

~/Desktop/ziptest
▶ ls
__main__.py test.py     test.pyc    ziptest     ziptest.zip

~/Desktop/ziptest
▶ chmod +x ziptest

~/Desktop/ziptest
▶ ./ziptest hi
hi

~/Desktop/ziptest
▶ mv ziptest /usr/local/bin/ziptest

~/Desktop/ziptest
▶ ziptest hello
hello

You don't need the .zip filetype suffix on the archive as Hikmat demonstrated above (tested on Mac OSX).

main.py

#!/usr/bin/env python
# encoding: utf-8
# file: __main__.py

import sys
from test import main

if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))

test.py

#!/usr/bin/env python
# encoding: utf-8
# file: test.py

import sys

def main(argv):
    if len(argv) > 0:
        print(argv[0])
    else:
        print('No arguments!')

if __name__ == '__main__':
    main(sys.argv[1:])
over 1 year ago ·