virtualenv is a tool for isolating your application in what is called a virtual environment. A virtual environment is a directory that contains the software on which your application depends. A virtual environment also changes your environment variables to keep your development environment contained. Instead of downloading packages, like Flask, to your system-wide — or user-wide — package directories, we can download them to an isolated directory used only for our current application. This makes it easy to specify which Python binary to use and which dependencies we want to have available on a per project basis.
Virtualenv also lets you use different versions of the same package for different projects. This flexibility may be important if you're working on an older system with several projects that have different version requirements.
When using virtualenv, you'll generally have only a few Python packages
installed globally on your system. One of these will be virtualenv
itself. You can install the virtualenv
package with Pip.
Once you have virtualenv on your system, you can start creating virtual
environments. Navigate to your project directory and run the
virtualenv
command. It takes one argument, which is the destination
directory of the virtual environment. Listing\~ shows what this looks
like.
$ virtualenv venv
New python executable in venv/bin/python
Installing Setuptools...........[...].....done.
Installing Pip..................[...].....done.
$
virtualenv
creates a new directory where the dependencies will be
installed.
Once the new virtual environment has been created, you must activate it by sourcing the bin/activate script that was created inside the virtual environment.
$ which python
/usr/local/bin/python
$ source venv/bin/activate
(venv)$ which python
/Users/robert/Code/myapp/venv/bin/python
The bin/activate script makes some changes to your shell's environment
variables so that everything points to the new virtual environment
instead of your global system. You can see the effect in code block
above. After activation, the python
command refers to the Python
binary inside the virtual environment. When a virtual environment is
active, dependencies installed with Pip will be downloaded to that
virtual environment instead of the global system.
You may notice that the shell prompt has been changed too. virtualenv prepends the name of the currently activated virtual environment, so you know that you're not working on the global system.
You can deactivate your virtual environment by running the deactivate
command.
(venv)$ deactivate $
3.1.1. virtualenvwrapper
virtualenvwrapper is a package used to manage the virtual environments created by virtualenv. I didn't want to mention this tool until you had seen the basics of virtualenv so that you understand what it's improving upon and understand why you should use it.
That virtual environment directory created in Listing adds clutter to your
project repository.
You only interact with it directly when activating the virtual
environment and it shouldn't be in version control, so there's no need
to have it in there. The solution is to use virtualenvwrapper. This
package keeps all of your virtual environments out of the way in a
single directory, usually ~/.virtualenvs/
by default.
To install virtualenvwrapper, follow the instructions in the documentation. See Box for that link.
Caution Make sure that you've deactivated all virtual environments before installing virtualenvwrapper. You want it installed globally, not in a pre-existing environment.
Now, instead of running virtualenv
to create an environment, you'll
run mkvirtualenv
:
$ mkvirtualenv rocket
New python executable in rocket/bin/python
Installing setuptools...........[...].....done.
Installing pip..................[...].....done.
(rocket)$
mkvirtualenv
creates a directory in your virtual environments folder
and activates it for you. Just like with plain old virtualenv
,
python
and pip
now point to that virtual environment instead of the
system binaries. To activate a particular environment, use the command:
workon [environment name]
. deactivate
still deactivates the
environment.
3.1.2. Keeping track of dependencies
As a project grows, you'll find that the list of dependencies grows with it. It's not uncommon to need dozens of Python packages installed to run a Flask application. The easiest way to manage these is with a simple text file. Pip can generate a text file listing all installed packages. It can also read in this list to install each of them on a new system, or in a freshly minted environment.
3.1.2.1. pip freeze
requirements.txt is a text file used by many Flask applications to list all of the packages needed to run an application. This code block shows how to create this file and the following one shows how to use that text file to install your dependencies in a new environment.
(rocket)$ pip freeze > requirements.txt $ workon fresh-env (fresh-env)$ pip install -r requirements.txt [...] Successfully installed flask Werkzeug Jinja2 itsdangerous markupsafe Cleaning up... (fresh-env)$
3.1.3. Manually tracking dependencies
As your project grows, you may find that certain packages listed by
pip freeze
aren't actually needed to run the application. You'll have
packages that are installed for development only. pip freeze
doesn't
discriminate between the two, it just lists the packages that are
currently installed. As a result, you may want to manually track your
dependencies as you add them. You can separate those packages needed to
run your application and those needed to develop your application into
require_run.txt and require_dev.txt respectively.