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
Written by Hikmat Dhamee
Related protips
5 Responses
This is an interesting tip. Where does the interpreter start execution of the scripts in the archive?
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...
@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.
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.
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:])