Wednesday, 18 November 2015

A Way to Deploy Python Programs

[...]we will use Java, because a jar file is easier to deploy.
This sentence occurs sometimes where I work. In this multi-environment place, a easy way to deploy your software is a fundamental requirement.
So, it seems deploying python programs is a hell: we have many ways to share with friends and colleagues our new shining application
  1. Create a pip archive and deploy it to a custom repository
  2. Create a zip from a virtualenv
  3. cx_freeze
  4. py2exe (windows only)
  5. py2app (Mac OS X only)
  6. debian/rpm/whatever
BUT I found two thing very interesting on Python3 and they give me a good idea to implement a simple but effective way to deploy programs written with our favourite language. Let's take a look and try to find a way to use them

Python ZIP

Python3 can run python application archived in a zip file. It will call __main__.py file and creates a separate directory (__pycache__) to store bytecode files. If you're using just the standard library, you can send this package to your customers. Just remember them to install python.

Python PIP Module

Pip is the standard package manager for python modules starting from Python3. It fetch informations from PyPi repository and download required modules and its dependencies.
This post born from a recent discovery I did: pip is also a python module. This means you can call it from a python script
import pip

pip.main(['install', "xlrd"])

Work on a Virtualenv

Let's create a new virtualenv. Virtualenv is a python tool to create virtual python environments with separate secondary packages.
me@home:program$ virtualenv-3.4 py34
Using base prefix '/usr'
New python executable in py34/bin/python3
Also creating executable in py34/bin/python
Installing setuptools, pip, wheel...done.
me@home:program$ ls
py34  __main__.py
me@home:program$ source py34/bin/activate
(py34)me@home:program$ 
Now we are working in a virtual enviroment, wich simulates a "clean, fresh installation" of python3.4. Now, let's install our required packages
me@home:program$ pip install xlrd
Collecting xlrd
Installing collected packages: xlrd
Successfully installed xlrd-0.9.4
xlrd is now installed just in our virtual environment.
Pip comes with a usefull command, freeze, wich tells us non-default packages installed in our environment
me@home:program$ pip freeze
wheel==0.24.0
xlrd==0.9.4
With a simple redirect we have a file that lists our dependencies: with few changes with a editor, we can modify it in a python list (deps) contained in a python module.

PythonCheckInstall

Take your __main__.py script and put these line on top
#!/usr/bin/env python
import os
import pip
import dependencies # This module contains our dependencies obtained with freeze

installed=os.path.isfile("~/.myprogram_installed")
if (not installed):
    for package in dependencies.deps:
        pip.main(['install', package])
    x = open("~/.myprogram_installed",'w')
    x.write("done")
    x.close()

# your program...
import xlrd
import ...
What does this procedure? It will check for a file installed in user's home directory called ".myprogram_installed". If it exists, script will proceed as programmed. Else, pip will install every package listed on file dependecies.txt. Now you can create a zip file and deliver it to every python-enabled station.

Just this?

Probably many things could be improved and some problems aren't contemplated: obviously your clients must install Python and they need an active connection to download dependencies. But this could a easy way to create a single, portable and executable file to deploy your python applications.

No comments: