I'm not happy with the way that I currently deploy Python code and I was wondering if there is a better way. First I'll explain what I'm doing, then the drawbacks:
- When I develop, I use virtualenv to do dependancy isolation and install all libraries using pip. Python itself comes from my OS (Ubuntu)
- Then I build my code into a ".deb" debian package consisting of my source tree and a pip bundle of my dependancies
- Then when I deploy, I rebuild the virtualenv environment, source foo/bin/activate and then run my program (under Ubuntu's upstart)
Here are the problems:
- The pip bundle is pretty big and increases the size of the debian package significantly. This is not too big a deal, but it's annoying.
- I have to build all the C libraries (PyMongo, BCrypt, etc) every time I deploy. This takes a little while (a few minutes) and it's a bit lame to do this CPU bound job on production
Here are my constraints:
- Must work on Python 3. Preferably 3.2
- Must have dependency isolation
- Must work with libraries that use C (like PyMongo)
I've heard things about freezing, but I haven't been able to get this to work. cx_freeze out of Pypi doesn't seem to compile (on my Python, at least). The other freeze utilities don't seem to work with Python 3. How can I do this better?
Wheel is probably the best way to do this at the moment.
Create a virtualenv on the deployment machine, and deploy a wheel along with any dependencies (also built as wheels) to that virtualenv.
This solves the problems:
- Having separate wheels for dependencies mean you don't have to redeploy dependencies that haven't changed, cutting the size of the deployment artefact
- Building big packages (such as lxml or scipy) can be done locally, and then the compiled wheel pushed to production
Also, it works fine with libraries that use C.