Virtual Environments

don't pollute

by Kurt Neufeld
@kneufeld

What is a virtual environment?

what is a regular environment?

The Python Environment

When you run a python application there's more than just one file involved. There's lots of files involved.

  • there's /usr/bin/python
  • there's your application
  • and most importantly for this talk...
  • there are the dependencies

Javascript Sucks

Who here heard about the whole leftpad fiasco the other week?

Basically it was dependencies run amok

Python Doesn't Suck

Now I'm not saying that leftpad could never happen in the Python community but so far it hasn't and that makes us better.

We do have the potential for lots of dependencies though.

PyPI has roughly 75,000 projects in it.

Dependencies

So lets say you have an older web app that runs Django 1.4 and it uses some package Foo, version 1.2

But now you want to make the Greatest Thing Ever ™ and it clearly needs the latest version of Django 1.9.5

But Django 1.9.5 needs Foo version 2.3!

But Foo 2.3 doesn't work with Django 1.4!

I guess you won't be able to make the Greatest Thing Ever ™ and now you'll have to live a life of poverty in your parents basement.

What were we talking about again?

Oh yeah, virtual environments.

Since the regular environment is clearly a one way trip to poverty in your parents basement it's now time to live long and prosper with virtual environments!

Virtual Environments

Basically, a virtual environment is nothing more than a copy of the python executable and some path munging.

But what sweet path munging it is.

Prep Work


easy_install pip # if required
pip install virtualenv

# you may want to install virtualenv from your distro but it will
# probably be an older version

# osx: brew install python-virtualenv
# debian/ubuntu: apt-get install python-virtualenv
# redhat family: yum install python-virtualenv
        

Construction


cd ~/src/project
virtualenv venv # by convention, usually named venv
source venv/bin/activate
which pip
which python
        

Environment


pip install django
pip install -r requirements.txt
        

requirements.txt

simply a list of packages and their versions


Django==1.6.4
Fabric==1.4.3
MySQL-python==1.2.5
Werkzeug==0.8.3
celery==3.1.12
django-celery==3.1.10
django-debug-toolbar==1.2
django-extensions==1.1.1
django-tastypie==0.12.1
        

Destruction


deactivate
rm ~/src/project/venv
        

Virtual Environment Cons

The activate/deactivate dance is both annoying and error prone, especially if you work on lots of different projects at the same time.

You also have virtual environments scattered all over the place.

But there's a solution to this, more abstraction!

Virtual Environment Wrapper

salient points from website...

  • organize all your virtenvs in one place eg. ~/.virtualenvs
  • Wrappers for managing your virtual environments (create, delete, copy).
  • Use a single command to switch between environments.
  • Tab completion for commands that take a virtual environment as argument.
  • User-configurable hooks for all operations
  • Plugin system for more creating sharable extensions

Virtual Environment Wrapper

I only care about the first point because I have a better workflow.

Class participation time, everybody get their laptops out because I'm going to show you how to automatically activate/deactivate a virtual environment.

Auto VENV

https://goo.gl/g6DdtJ

https://www.burgundywall.com/post/automatically-activate-virtualenv

or just goto burgundywall.com and search for 'venv'

Auto VENV

  • install virtualenv and virtualenvwrapper
  • mkdir ~/.virtualenvs
  • copy the bash function into your .bashrc
  • source .bashrc
  • mkdir ~/src/project_name
  • touch ~/src/project_name/.venv
  • mkvirtualenv project_name
  • deactivate
  • cd ~/src/project_name
  • cd ..

Auto VENV

add the following to .bashrc too

it might not work exactly as typed


export PS1="[\u@\h \[\e[1;34m\]\w\[\e[0m\]]\n\\$ "
export PROMPT_COMMAND=prompt_command_collection
        

function prompt_command_collection() {
    printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"

    handle_virtualenv
    export PS1="[\u@\h \[\e[1;34m\]\w\[\e[0m\]${venv_ps1}" "]\n\\\$ "
}
        

ProTips ™

  • don't need to install as root (or use sudo)
  • python doesn't have to be cpython, it can be pypy
  • don't use virtualenv, use virtualenvwrapper
  • better than autoenv since the virtenv is deactivated
  • the only allowed global installs are:
    • pip
    • ipython
    • virtualenv & virtualenvwrapper

ProTips ™

  • if you want to use a virtenv from an alias/script/cron/etc then provide the full path to python
    
    alias fab="/home/kneufeld/.virtualenvs/fabric/bin/fab"
  • 
    # from a script
    /home/kneufeld/.virtualenvs/project/bin/python \
    /home/kneufeld/src/project/app.py

ProTips ™

.venv can be a bit fancy


if [ `uname -o` == "Darwin" ]; then
	VENV='project_name'
else
	VDIR=`pwd`/virt
fi
        

VDIR takes precendence over VENV

VENV is current directory by default

Note

In Python 3.5 there is pyenv which is more baked in but I haven't used it so can't speak to it.

Questions?

thanks for listening