Easily Switch Between Python2 and Python3 with pyenv

Look, it’d clearly be easier if the world could all get on Python3, or if the split had done a better job with backwards compatibility. But that didn’t happen, and sometimes you need to switch between Python versions.

You might be thinking “it’s so easy to upgrade scripts from Python 2 to 3 using something like 2to3.” You’d be partially right, but

  1. sometimes there’s bit- or byte-level processing that is difficult to easily upgrade and
  2. sometimes you just want things to work. This is doubly true if you’re under a time crunch (such as a CTF challenge).

And that’s where pyenv comes in.

What is pyenv?

Pyenv bills itself as “simple python version management”. Here’s what switching from python 2 to python 3 in a shell looks like:

$ python -V
Python 2.7.16
$ pyenv local 3.7.2
$ python -V
Python 3.7.2

You might be thinking “so what, I can type python2 or python3 depending on the script”.

Pyenv also manages pip (python’s package manager) for you.

So, if you select Python 2.7.18 with pyenv, any packages you install with that version of Python will managed separately.

That means you can change the Python version on a per-user or per-project basis, and search commands from multiple Python versions at a glance.

It does this by adding a shims directory at the front of your path, which takes python or pip commands and passes them along to pyenv.

Pyenv Overview

Here’s what pyenv options are available:

$ pyenv
pyenv 2.1.0
Usage: pyenv <command> [<args>]

Some useful pyenv commands are:
   --version   Display the version of pyenv
   commands    List all available pyenv commands
   exec        Run an executable with the selected Python version
   global      Set or show the global Python version(s)
   help        Display help for a command
   hooks       List hook scripts for a given pyenv command
   init        Configure the shell environment for pyenv
   install     Install a Python version using python-build
   local       Set or show the local application-specific Python version(s)
   prefix      Display prefix for a Python version
   rehash      Rehash pyenv shims (run this after installing executables)
   root        Display the root directory where versions and shims are kept
   shell       Set or show the shell-specific Python version
   shims       List existing pyenv shims
   uninstall   Uninstall a specific Python version
   version     Show the current Python version(s) and its origin
   version-file   Detect the file that sets the current pyenv version
   version-name   Show the current Python version
   version-origin   Explain how the current Python version is set
   versions    List all Python versions available to pyenv
   whence      List all Python versions that contain the given executable
   which       Display the full path to an executable

See `pyenv help ' for information on a specific command.
For full documentation, see: https://github.com/pyenv/pyenv#readme

For the most part, you can get away with only using the following commands:

  • pyenv install <version #> to install a given python version
  • pyenv versions to see which versions are installed
  • pyenv local <version #> or pyenv shell <version #> to set the version you’d like to use

Installation

You can use this library to quickly install pyenv.

If you’d rather build from a git checkout, view these instructions.

If you are on Mac, you can use brew install pyenv to install via Homebrew.

If you are Windows, you can’t use pyenv but try out pyenv-win.

Then find the relevant OS/shell section in this part of the pyenv set up instructions. If you aren’t sure which shell you’re using, type echo $SHELL in a terminal.

One more note: if you are having issues on MacOS where the pyenv version returns the expected value but python -V does not, make sure you have eval "$(pyenv init --path) in your bash profile, and then restart the shell.