In this tutorial I'll show you how I prepare my machine for Python development after installing Ubuntu or one of its derivatives. There are many ways to do this, with different tools and techniques. Here I am sharing the way that works best for me.
These are the two goals of this process:
- not to mess with the operating system's Python interpreter;
- be able to work on projects that use different Python versions and different Python libraries.
As a practical example, we will create three Python projects:
- A Django project with Python 3.7;
- A Mezzanine project with Python 3.7 too;
- A Flask project with Python 2.7.
We will begin with a fresh installation of Ubuntu 19.04.
We will build some Python versions, and for that we will need to install some system dependencies. We'll follow the recommendation of the subsection "Ubuntu/Debian/Mint" of pyenv's wiki's "Suggested build environment" section. As of 2019-06-11, they are:
$ sudo apt-get update; sudo apt-get install --no-install-recommends make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
So we open a Terminal (
Ctrl + Alt + T) and install the dependencies:
We'll also need Git:
$ sudo apt-get install git
After the system dependencies we'll install pyenv. Among other things, pyenv lets us install different Python versions in our system.
Below, we're following the "installation" section of pyenv's GitHub page. Be sure to check that page for updated instructions.
$ git clone https://github.com/pyenv/pyenv.git ~/.pyenv
export PYENV_ROOT="$HOME/.pyenv" export PATH="$PYENV_ROOT/bin:$PATH" if command -v pyenv 1>/dev/null 2>&1; then eval "$(pyenv init -)" fi
Note: these may take a long time to complete, for pyenv will download and build CPython from source for each version.
$ pyenv install 2.7.16 $ pyenv install 3.7.3
As we can see in the screenshot, the Python versions have been installed in
$HOME/.pyenv/versions. We can run both interpreters directly to verify that they are working properly:
However, we will not be installing libraries in these Python interpreters. They will be the base interpreters for our projects. Actually, each project will have its own isolated Python environment, with its own Python interpreter and its own libraries.
virtualenv is a great tool for creating these isolated environments. Installing it on Ubuntu is straightforward:
$ sudo apt-get install virtualenv
The creation of the environments is easy too. We'll create them on the next sessions.
Let's create a directory
$HOME/projects/django_project and then create an isolated Python environment for this project in
$HOME/projects/django_project/.venv_django using the Python 3.7.3 that we installed earlier.
$ mkdir ~/projects $ mkdir ~/projects/django_project $ cd ~/projects/django_project $ virtualenv .venv_django --python=$HOME/.pyenv/versions/3.7.3/bin/python
In the screenshot, we can see that an environment was created in the new
.venv_django directory, and it contains its own Python interpreter, along with some other tools.
We need to activate this environment so we can use its Python interpreter and install libraries on it. After the activation, executing
python (the Python interpreter) or
pip (the Python package manager) will use the versions of these tools that are inside the environment.
The activation is essential. If we skip it, we will end up messing with the operating system's Python interpreter, and that's exactly what we don't want to do.
To perform the environment activation, we need to
source the script
bin/activate located inside the environment directory.
$ source .venv_django/bin/activate
Notice that, when the environment is activated, the prompt is prefixed with the name of the environment's directory.
Now, with the environment properly activated, we can install Django with
pip, create the Django project and run it.
$ pip install Django $ django-admin.py startproject django_project . $ python manage.py runserver
To quit the Django development server, just hit
Ctrl + C.
Now we will create a Python environment for a Mezzanine project, so we must deactivate the currently activated environment (the Django one) and leave the Django project directory:
$ deactivate $ cd ..
In a similar fashion, now we will
- create the environment for the Mezzanine project (based on Python 3.7.3 again);
- activate the environment;
- install the libraries that we need;
- create and run the project.
$ mkdir mezzanine_project $ cd mezzanine_project $ virtualenv .venv_mezzanine --python=$HOME/.pyenv/versions/3.7.3/bin/python $ source .venv_mezzanine/bin/activate $ pip install mezzanine $ mezzanine-project myproject . $ python manage.py createdb $ python manage.py runserver
To quit the Django development server (Mezzanine is built on top of Django), just hit
Ctrl + C again.
Before moving to the last project (the Flask one), let's deactivate the Mezzanine environment and leave the project directory:
$ deactivate $ cd ..
For the Flask project, the process will be similar, but the environment will be based on Python 2.7.16 instead. Flask doesn't have an autogenerator of basic projects like Django and Mezzanine do, therefore we'll need to write a little bit of code in order to have a minimal Flask application.
$ mkdir flask_project $ cd flask_project $ virtualenv .venv_flask --python=$HOME/.pyenv/versions/2.7.16/bin/python $ source .venv_flask/bin/activate $ pip install flask $ touch app.py
Let's enter the following code in the file
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, World'
Now we can run the Flask app to make sure that it works as expected.
$ flask run
To quit the Flask development server, just hit
Ctrl + C. Then, let's deactivate the environment that we created for the Flask project and leave its directory.
$ deactivate $ cd ..
- We use Pyenv to install different Python interpreters
- We use virtualenv to create isolated environments for different Python projects
- We activate each environment before installing the libraries they need
- When an environment is activated, the prompt is prefixed with the name of the environment's directory
- We deactivate an environment when we don't need to use it
- We never touch the operating system's Python interpreter
- Each environment has its own isolated set of installed libraries, as shown below:
That's it! Do you have a different approach which works best for you?