Managing Python Environments With Virtualenv
Embrace core best-practices in Python by managing your Python packages using virtualenv and virtualenvwrapper.
So you've decided to learn Python - good on you (it was a solid choice). Perhaps your experience with Python thus-far has mostly been within bootcamps or classwork, or any context where you've been provided an environment to type code in and get the output. You're comfortable enough with the language itself, but now you actually need to code a real program on a real computer.
One of the most frustrating parts of learning Python is there seems to be a missing section in every Python course which covers how Python works on your physical machine. To write meaningful code, we need to understand the basics of what happens on our machine when we run a Python app. You've heard that you should be using "virtual environments" when writing Python apps, but before we even get there, let's talk about the Python Path.
The Python Path: Your Local Installation of Python
Every modern OS has some version of Python pre-installed- probably a version of Python 2.7. In the same way we use applications to open files, we use our local Python installation to run Python scripts, either via the Python shell or by executing Python code in .py files.
Let's find out more about your local Python installation. Open up your terminal and type the following:
You should see an output as such:
Cool, so you're running Python 2.7 as expected. Just making sure here, folks. To find out where this Python executable is, do the following:
You should see something like this:
Aha! This is where your local Python is installed, AKA the "Python Path." Not only is this where Python lives, but it's also where Python likes to install all of its pip packages by default (I'm assuming you're familiar with pip by now).
Installing Packages with pip
pip install a Python package, pip will install the package relative to our Python Path by default. This seems fine at first: you'll be able to use the packages you installed in your scripts, but soon every package you install will live in the same place. This becomes a problem when we need to work with other people who want to use our Python app... how do we tell them which packages to install easily if we have hundreds of irrelevant packages from other projects? Besides, its best practice in software development to separate concerns, and only use what is necessary. We don't want packages from project A to be mashed in with packages from project B.
This is the problem that "virtual environments" solve. In Python terms, a virtual environment is a place to save Python packages which are specific to a project in a location designated for that project only.
Environments With Virtualenv
While keeping all your Python packages in the same directory on your machine may be nice at first, this becomes an unmanageable problem when you suddenly find yourself managing multiple projects, each of which may contain different libraries and versions of such libraries. As such, it is best practice to always encapsulate the library dependancies of a project by utilizing one of Python's environment manages, such as virtualenv.
Virtualenv is the oldest and most common method for managing Python environments. When we refer to a "virtual environment" in Python, we're not implying the creation of a "fully-fledged" environment like a Docker container, Virtual Box vm, etc. The scope of a Python "virtual environment" exclusively refers to a directory which Python will work from to install and utilize Python packages. Some virtual environment solutions even allow you to run versions of Python which differ from our default install, but we'll get to that later.
Creating an environment with virtualenv will create a folder in the user's current directory. This folder represents an environment which can then be 'activated.' This is a way of explicitly using the new environment directory in place of PYTHONPATH to handle Python packages. As such, we can create as many environments as we want without worrying about package conflicts.
If you intend on using Python 2 for some reason (which I highly recommend against), you begin by installing the virtualenv package:
With virtualenv installed, we can create a Python "environment" in any project directory want.
cd to wherever you'd like to start a Python project, and run the following command where "myenv" is your desired environment name (this is arbitrary):
Alternatively, you can do the same in Python3 without installing any packages and simply running the following:
You should see output like this:
Using base prefix '/usr/local/Cellar/python/3.7.4_1/Frameworks/Python.framework/Versions/3.7' New python executable in /Users/toddbirchard/projects/virtualenv-tutorial/myenv/bin/python3.7 Also creating executable in /Users/toddbirchard/projects/virtualenv-tutorial/myenv/bin/python Installing setuptools, pip, wheel... done.
If you do a quick
ls, you'll see a folder was created in the current directory named myenv! That folder is the new home of your virtual environment; every time you install a Python package with the environment active, that package will be saved to the directory of said environment (as opposed to saved on your machine's Python path).
Using Your Environment
We need to 'activate' virtual environments when we intend to use them. There's an execut
You should notice in the terminal that once this is activated, the command line will always state that the user is working out of the activated environment until otherwise changed.
Alternative Methods of Virtual Environment Management
Virtualenv is the oldest method of managing Python environments but is by no means the best for every situation. Pipenv is an easy-to-use alternative which has done me well over the years. If you’re a bit more adventurous, Poetry might be what you’re looking for. Of course, if you’re using Anaconda, you can create environments using the conda command as well.