virtualenv HOWTO
virtualenv HOWTO
An introduction to distutils/pip and virtualenv to manage
dependencies in Python.
Unix basics
The $PATH environment variable contains a list
of directories where executable programs are searched for.
$ ls
slides.html
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:…
$ which ls
/bin/ls
$ /bin/ls
slides.html
Unix basics: shebang
When an executable program start with #! (called
Shebang) the OS will actually append the program name to
the rest of the line and execute that.
$ which meld
/usr/bin/meld
$ head -n 1 /usr/bin/meld
#!/usr/bin/python
$ meld &
$ pgrep -l meld
24666 /usr/bin/python /usr/bin/meld
Unix basics: shebang, continued
The shebang must be an absolute path to an executable, optionally with
parameters.
/usr/bin/env can search $PATH
like shells do.
$ head -n 1 /usr/bin/ipython
#!/usr/bin/env python
Python basics
sys.path is a list of directories where modules are
searched for when importing.
>>> import sys, pprint
>>> pprint.pprint(sys.path)
['',
'/usr/lib/python2.6',
'/usr/lib/python2.6/lib-dynload',
'/home/simon/.local/lib/python2.6/site-packages',
'/usr/lib/python2.6/dist-packages', …]
>>> pprint.__file__
'/usr/lib/python2.6/pprint.pyc'
virtualenv
Give the virtualenv command a directory name to create
a new environment.
$ virtualenv ./test-env
New python executable in ./test-env/bin/python…
$ ls test-env
bin include lib
$ ls test-env/bin
activate easy_install pip python …
$ head -n 1 test-env/bin/pip
#!/home/simon/test-env/bin/python
virtualenv: activate
Run the activate script with the
source command (also .) to add the
environment to $PATH.
$ . test-env/bin/activate
(test-env)$ echo $PATH
/home/simon/test-env/bin:/usr/local/bin:/usr/bin:…
(test-env)$ which python
/home/simon/test-env/bin/python
(test-env)$ deactivate
$
activate is for convenience only. Using
test-env/bin/python in a shell or a shebang (like pip does)
would Just Work™.
pip: installing packages
pip can download and install Python packages and their
dependencies in a virtualenv, without polluting the system or being
root.
(test-env)$ pip install Frozen-Flask
Downloading/unpacking Frozen-Flask…
Downloading/unpacking Flask (from Frozen-Flask)…
Downloading/unpacking Werkzeug>=0.6.1 (from Flask→Frozen-Flask)…
Downloading/unpacking Jinja2>=2.4 (from Flask→Frozen-Flask)…
Successfully installed Frozen-Flask Flask Werkzeug Jinja2
virtualenv: sys.path
The environment’s python automatically has its
sys.path changed:
(test-env)$ python
>>> import sys, pprint
>>> pprint.pprint(sys.path)
['',
'/home/simon/test-env/lib/python2.6',
'/home/simon/test-env/lib/python2.6/site-packages',
'/usr/lib/python2.6',
'/usr/lib/python2.6/dist-packages', …]
>>> import flask
>>> flask.__file__
'/home/simon/test-env/lib/python2.6/site-packages/flask/__init__.pyc'
setup.py: describe your dependencies
Add a setup.py file to your own projects to describe
their dependencies:
(test-env)$ mkdir -p test-project/myapp
(test-env)$ touch test-project/myapp/__init__.py
(test-env)$ cat > test-project/setup.py
from setuptools import setup, find_packages
setup(
name='MyApp',
packages=find_packages(),
install_requires=["Flask", "docutils"])
pip editables
pip install -e or --editable with a directory
name installs a package by adding to sys.path instead of
copying files, so you don’t need to reinstall for every change.
(test-env)$ pip install -e ./test-project/myapp
…Successfully installed docutils MyApp
(test-env)$ python
>>> import sys, myapp
>>> myapp.__file__
'/home/simon/test-project/myapp/__init__.pyc'
>>> sys.path
[… '/home/simon/test-project', …]
Trick #1: activate and bash history
You will re-activate the same virtualenv often (at least for every new
terminal you open.)
To make that easier, source activate with a path that
does not depend on the current directory:
$ . ~/test-env/bin/activate
Next time, find it with your shell’s command history (often
CTRL+R.)
Trick #2: /usr/bin/env and virtualenvs
When a script uses /usr/bin/env python instead of eg.
/usr/bin/python as a shebang, it will use the activated
virtualenv’s python.
I changed /usr/bin/ipython that way on my system so that
I can use it without installing it in every virtualenv.
Trick #3: pip download cache
When using more than one virtualenv, you will install the same packages
over and over. pip’s download cache can speed things up a bit:
$ mkdir -p ~/.pip
$ cat > ~/.pip/pip.conf
[install]
download-cache=~/.pip/download-cache
Trick #4: virtualenvwrapper
virtualenvwrapper manages virtualenvs for you.
- mkvirtualenv name creates and activates a new environment
- lsvirtualenv list available environments
- workon name activates
- rmvirtualenv name removes
- Also has hooks to run custom code on any operation, tab-completion
on environment names, …