earn the White PyBites Ninja earn the Yellow PyBites Ninja earn the Orange PyBites Ninja right arrow earn more PyBites Ninja belts and certificates
The best way to learn to code in Python is to actually use the language.

Our platform offers effective Test Driven Learning which will be key to your progress.


Join thousands of Pythonistas and start coding!


Join us on our PyBites Platform
Click here to code!

Zip and ship, make an executable zipfile of your py project

Posted by Bob on Sun 25 December 2016 in Packages • 2 min read

Get started

First of all, new in version 3.5 is zipapp which makes this easier. As not everybody is on this version yet, I will show the manual way to do this.

We're going to use the code of our last post: Get a weekly digest from a Pelican blog.

Step by step

OK here we go:

$ git clone https://github.com/pybites/blog_code zip-example
Cloning into 'zip-example'...
remote: Counting objects: 22, done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 22 (delta 4), reused 22 (delta 4), pack-reused 0
Unpacking objects: 100% (22/22), done.
Checking connectivity... done.

$ cd zip-example/pybites_digest/
$ mkdir archive && cd $_
$ cp ../digest.py __main__.py

# Note that where I say python3 and pip3 for you it might be python and pip

$ pip3 install -r ../requirements.txt --target=packages
Collecting feedparser==5.2.1 (from -r ../requirements.txt (line 1))
Installing collected packages: feedparser
Successfully installed feedparser-5.2.1

$ touch packages/__init__.py
$ ls *
__main__.py
packages:
__init__.py         <dependencies>

# edit the main script to use the locally installed package (doing 'in place' edit)
$ perl -pi -e 's/import feedparser/import packages.feedparser as feedparser/g' __main__.py

# zip it up
$ zip my_script.zip -r *
adding: __main__.py (deflated 55%)
adding: packages/ (stored 0%)
adding: packages/__init__.py (stored 0%)
adding: packages/__pycache__/ (stored 0%)
adding: packages/__pycache__/feedparser.cpython-35.pyc (deflated 59%)
adding: packages/feedparser-5.2.1.dist-info/ (stored 0%)
adding: packages/feedparser-5.2.1.dist-info/DESCRIPTION.rst (stored 0%)
adding: packages/feedparser-5.2.1.dist-info/INSTALLER (stored 0%)
adding: packages/feedparser-5.2.1.dist-info/METADATA (deflated 64%)
adding: packages/feedparser-5.2.1.dist-info/metadata.json (deflated 58%)
adding: packages/feedparser-5.2.1.dist-info/RECORD (deflated 40%)
adding: packages/feedparser-5.2.1.dist-info/top_level.txt (stored 0%)
adding: packages/feedparser-5.2.1.dist-info/WHEEL (stored 0%)
adding: packages/feedparser.py (deflated 74%)

$ echo '#!/usr/bin/env python3' > my_script
$ cat my_script.zip >> my_script
$ chmod ug+x my_script

# to prove it shows the feedparser package is not installed in my main py3 installation
$ python3
Python 3.5.1 |Anaconda 4.0.0 (x86_64)| (default, Dec  7 2015, 11:24:55) 
[GCC 4.2.1 (Apple Inc. build 5577)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import feedparser
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named 'feedparser'
>>>

# yet it works with the zipped package :)
$ ./my_script 
Get a weekly digest from a Pelican blog
http://pybit.es/blog-digest.html
In this post a script we use to get a weekly digest of our posts.
--

2016 py articles and useful books
http://pybit.es/py-articles-books2016.html
Some of my Python articles I posted on my blog this year and useful books
...
...

# I can put it in my $HOME/bin now as well:

$ cp my_script ~/bin/pybites_digest
$ which pybites_digest
/Users/bbelderb/bin/pybites_digest
$ pybites_digest
Zip and ship, make an executable zipfile of your py project
http://pybit.es/zip-and-ship.html
In this post I show an example how you can distribute your code as an executable zipfile, a neat trick I discovered in Chapter 6 of The Hitchhiker's Guide to Python
--
...
...

Conclusion

Although I would not use this for bigger projects (you lose debugging abilities), this is still a neat way to package up and ship scripts. Consumers don't have to worry about installing dependencies / doing any pre-work.


See an error in this post? Please submit a pull request on Github.