How to Setup a Python3 Development Environment (2018 Edition)

June 06, 2018

Context
After needing to setup my dev environment on a few different machines/servers, I decided to document it. Eventually, I’ll make it into an Ansible playbook. I use Digital Ocean droplets. The initial setup is done by following this tutorial:

Initial Server Setup with Ubuntu 16.04

The Pieces

  1. pyenv
  2. pyenv-virtualenv
  3. pyenv-virtualenvwrapper


Prep

In order to get pyenv running, we need the following libraries:

sudo apt-get install -y make build-essential sqlite3 libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev \
xz-utils tk-dev


pyenv & pyenv-virtualenv

Using the pyenv-installer, install pyenv and pyenv-virtualenv

curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash

Then install a version of python, since virtualenvwrapper needs a verion:

pyenv install 3.5.2

Then set the global python to the installed version:

pyenv global 3.5.2


pyenv-virtualenvwrapper

Install it as a plugin:

git clone https://github.com/pyenv/pyenv-virtualenvwrapper.git $(pyenv root)/plugins/pyenv-virtualenvwrapper

Create your projects directory:

mkdir ~/projects

Once installed, add the following lines to the end of your bashrc:

export WORKON_HOME=$HOME/.virtualenvs
export PROJECT_HOME=$HOME/projects
export PATH="/home/<user>/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
export PYENV_VIRTUALENVWRAPPER_PREFER_PYVENV="true"
pyenv virtualenvwrapper

Then source the bashrc in order to use pyenv and virtualenv.

source ~/.bashrc

Use virtualenv like normal:

$ pyenv global 3.5.2
$ mkproject funproject
$ workon funproject
$ python -V
3.5.2

$ pyenv global 2.7.15
$ mkproject awseomeproject
$ workon awesomeproject
$ python -v
2.7.15

One thing that’s still not copacetic is that for python 3.5.2 projects created by mkproject, pyenv symlinks the python (which is good) into the new virtualenv.
But for 2.7.15 it copies the binary into the virtualenv. Need to figure out if this is expected behavior or I messed up in this setup