Skip to main content

Pyenv to manage multiple Python versions

1. Intro to Pyenv

In this article, we will learn about Pyenv to manage multiple Python versions effectively.

Python comes bundled with Mac OS, however, they are 2.X version. Python 2.X is outdated and they are not suggested for any new development.

The latest Python version is 3.8 (As of 20 April 2020). When we install Python 3.8 using the installer package and try to run python the command we were surprised to see it's still pointing to the python 2.X version.

Python website download page\
% python

WARNING: Python 2.7 is not recommended. 
This version is included in macOS for compatibility with legacy software. 
Future versions of macOS will not include Python 2.7. 
Instead, it is recommended that you transition to using 'python3' from within Terminal.

Python 2.7.16 (default, Dec 13 2019, 18:00:32) 
[GCC 4.2.1 Compatible Apple LLVM 11.0.0 (clang-1100.0.32.4) (-macos10.15-objc-s on darwin
Type "help", "copyright", "credits" or "license" for more information.
% pip

To use newly installed python 3.8, we have to use python3 commands.

 % python3
Python 3.8.2 (v3.8.2:7b3ab5921f, Feb 24 2020, 17:52:18) 
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

One of my tools doesn't support Python 3.8, a curse of the most recent version. I have to install Python 3.7 for this tool to work fine.

I started pondering, what is the best way to manage multiple Python versions, where I can pick and choose the default Python version for specific tools. Without any utility tool, there was a lot of effort required to achieve the same, which involve, changing alias and PATH variables in the Mac very frequently.

Fortunately, we have Pyenv((Pyenv Github Project Page)) tool, which helps us in managing multiple Python versions effectively on Mac. It does the following work:

  1. Global Python version per user basis.
  2. Python version per-project basis.
  3. Allowing overriding of Python version using environmental variable.

I used Pyenv installer ((Pyenv Installer)) to install it, however, you can use homebrew and git checkout also. Read detail about installation from the Pyenv Github page((Pyenv installation guide)).

Once you are done with Pyenv installation you can use the following commands to manage.

# Check all available commands
% pyenv commands

2. Installation of a Python version - pyenv install

# Install a new version of Python
% pyenv install <version>

# See all available versions for installation
% pyenv install --list

One thing which annoyed me was no support to use the existing installed Python with Pyenv, there are some plugin solutions ((Pyenv plugin to use existing Python)), which don't work for me.

I believe for me to use Pyenv require me to remove all the existing Python installations (of course not the System required 2.x version) and use them exclusively for managing my Pythons installations.

3. Uninstallation of a Python version

% pyenv uninstall <version>

4. Setting global (User wise) Python version

# Set global default version to 3.7.8
% pyenv global 3.7.8

# Check versions info
% pyenv versions

# Setting multiple global versions with default to 3.7.8
% pyenv global 3.7.8 2.7.6

% python --version
Python 3.7.8
% python2.7 --version
Python 2.7.6
% python3.7 --version
Python 3.7.8

5. Setting local (Application wise) Python version

Assume we have a Python application at the/python-app folder, we want to run this application with a different Python Version than global. We can easily do so using Pyenv local command, which creates a file called .python-version in the current directory to save Python local version configurations.

# Change to application directory

% cd /python-app

% pyenv local 2.7.6

# Now when we will run python command it will run as version 2.7.6, overriding the global version
% python --version
Python 2.7.6

# If we want to rollback the local setting to global
% pyenv local --unset

Just like pyenv global configuration to keep multiple versions, we can do a similar setting for local.

6. Conclusion

I believe Pyenv is a smart choice for Python geeks to manage multiple Python versions on Mac OS and other OS (including Windows) without much hassle.


Popular posts from this blog

Working with request header in Jersey (JAX-RS) guide

In the  previous post , we talked about, how to get parameters and their values from the request query string. In this guide learn how to get request header values in Jersey (JAX-RS) based application. We had tested or used the following tools and technologies in this project: Jersey (v 2.21) Gradle Build System (v 2.9) Spring Boot (v 1.3) Java (v 1.8) Eclipse IDE This is a part of  Jersey (JAX-RS) Restful Web Services Development Guides series. Please read Jersey + Spring Boot getting started guide . Gradle Build File We are using Gradle for our build and dependency management (Using Maven rather than Gradle is a very trivial task). File: build.gradle buildscript { ext { springBootVersion = '1.3.0.RELEASE' } repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") } } apply plugin: 'java' apply plugin: 'eclipse' a

FastAPI first shot

Setup on my Mac (Macbook Pro 15 inch Retina, Mid 2014) Prerequisite Python 3.6+ (I used 3.7.x. I recently reinstalled OS after cleaning up disk, where stock Python 2.7 was available. I installed Pyenv and then used it to install 3.7.x). I already had a git repo initialized at Github for this project. I checked that out. I use this approach to keep all the source code safe or at a specific place 😀. I set the Python version in .python-version file. I also initialize the virtual environment using pyenv in venv folder. I started the virtual environment. FastAPI specific dependencies setup Now I started with basic pip commands to install dependency for the project. I saved dependencies in requirements.txt  the file. Minimal viable code to spin an API Server FastAPI is as cool as NodeJS or Go Lang (?) to demonstrate the ability to spin an API endpoint up and running in no time. I had the same feeling for the Flask too, which was also super cool. app/ from typing i

Jersey (JAX-RS) @FormParam HTML form data handling

There are multiple ways for consuming HTML form data (application/x-www-form-urlencoded) in Jersey. Using @FormParam annotation we can inject Form values in the Resource method. We can use it just like other @*Param. Jersey resource method needs to know they have to handle HTML form data, for it we explicitly specify  @Consumes("application/x-www-form-urlencoded") . There are multiple ways in which we can handle HTML form data using Jersey. Injecting Form data using @FormParam is one of them. Use @FormParam Using @FormParam we can inject specific HTML form parameters values in the Resource method. Its use is similar to other @*Param annotations. File: package in.geekmj.resource; import; import; import; import; import; import; import; import; import