As with any programming language, Python uses package managers (pip in this case) to manage the addition of libraries to be called at runtime. By default, installing a Python library with pip will install that package to the default Python path, which is the default folder from which Python stores its installed packages. For reference, you can determine you Python path via the following in the Python shell:

import sys

['', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-old', '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload', '/Library/Python/2.7/site-packages', '/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python', '/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/PyObjC']

Without any other specification, Python will always look in the Python path at runtime to locate and execute any packages imported by a script. For example, let's say I were to run a script called which attempts to import the 'requests' library, as such:

import requests

Running python in your terminal will attempt to look for the library in your generic python path.

Environments With Virtualenv

While keeping all your Python packages in one place 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. 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.


Install virtualenv via the following:

$ pip3 install virtualenv

With virtualenv installed, we can then create the environment. cd to the directory of your choice (preferably the one which you're planning to hold your project) and create an environment with the name of your choice:

$ virtualenv myenv

Using base prefix '/usr/local/Cellar/python/3.6.4_4/Frameworks/Python.framework/Versions/3.6'
New python executable in /Users/toddbirchard/myenv/bin/python3.6
Also creating executable in /Users/toddbirchard/myenv/bin/python
Installing setuptools, pip, wheel...done.

A folder should now have been created in the current directory. 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).


Now that the environment has been created, it must be 'activated'.

$ source myenv/bin/activate

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.