
This article contains affiliate links. See my affiliate disclosure for more information.
Beginners should install Python with the official python.org installers. But the installer workflow isn&apost very efficient for professional developers working on multiple projects — or any project that supports multiple Python versions.
In this guide, I&aposll show you how to:
- Install multiple versions of Python with
pyenv. - Install global utilities like
blackandflake8withpipx. - Manage project dependencies with
pip-tools.
Install Python With pyenv
pyenv allows you to install multiple versions of Python and switch between them as needed. To install pyenv, run the command below that corresponds to your OS.
macOS/Linux
Use the automatic installer below, or see the README for more options:
curl https://pyenv.run | bashYou&aposll need to restart your shell when you&aposre done:
exec "$SHELL"Windows
Install with PowerShell below, or see the README for more options:
Invoke-WebRequest -UseBasicParsing -Uri "https://raw.githubusercontent.com/pyenv-win/pyenv-win/master/pyenv-win/install-pyenv-win.ps1" -OutFile "./install-pyenv-win.ps1"; &"./install-pyenv-win.ps1"pyenv is only compatible with Unix/Linux operating systems. Windows users must use the separately maintained pyenv-win fork. pyenv and pyenv-win share the same CLI commands, so this guide works for every OS.Once pyenv or pyenv-win is installed, run pyenv install 3.11 to install the latest version of Python 3.11:
pyenv install 3.11At the time of the writing, the latest version is 3.11.1.
Use a different version prefix or a specific version number to install other versions of Python. For example, the following command installs the latest version of Python 3.10:
pyenv install 3.10To use a specific Python version that you&aposve installed, run python global:
pyenv global 3.11.1Now your python3 command points to Python 3.11.1.
.python-version containing a specific Python version number in your project&aposs root directory. Whenever you cd into the project&aposs folder, pyenv will automatically switch your interpreter to the version specified in .python-version.Install Global Utilities With pipx
pipx is a Python package installer that installs applications and command-line utilities in isolated environments and makes them available globally.
This is particularly helpful for tools like black and flake8, as they can be installed once and used across multiple projects while still taking into account project-specific configuration files.
You can install pipx with pip:
python3 -m pip install pipxBefore you can use pipx, you need to add it to PATH:
python3 -m pipx ensurepathpipx links applications it installs to the same Python executable that was originally used to install pipx.Consequently, when you invoke applications installed with
pipx, those applications will run using the pipx Python executable. (Except for ipython, which will detect and use project-specific virtual environments.)This is generally not an issue and may even be beneficial as it isolates tools from project dependencies. But be warned: Uninstalling the
pipx Python executable renders any pipx-installed tools pointing to it unusable.Frustratingly, you must install
pipx for every version of Python that you install with pyenv.Some of the tools I install with pipx are:
black: My preferred Python auto-formatter.flake8: My preferred Python code linter.ipython: My preferred Python REPL.
The following commands install all three tools in three separate environments:
pipx install black
pipx install flake8
pipx install ipythonNow you can use these tools as you normally would across all your projects without installing them in every project&aposs environment.
A Note For VS Code Users
If you use Python for VS Code, you&aposll need to point your flake8 path to the right location. If you don&apost, you&aposll see a pop-up that says "flake8 is not installed" every time you open VS Code.
Run pipx list to list every app installed by pipx. The application install path is displayed on the second line of output:
$ pipx list
venvs are in /Users/damos/.local/pipx/venvs
apps are exposed on your $PATH at /Users/damos/.local/bin
package black 22.12.0, installed using Python 3.11.1
- black
- blackd
package flake8 6.0.0, installed using Python 3.11.1
- flake8
package ipython 8.9.0, installed using Python 3.11.1
- ipython
- ipython3In my case, apps are installed in /Users/damos/.local/bin. Now run which flake8 to see which executable the flake8 command points to:
$ which flake8
/Users/damos/.local/bin/flake8Copy this path to your clipboard.
which flake8 should show flake8 in the same directory that pipx uses to install applications.If it doesn&apost, you may have previously installed
flake8 with a Python version that isn&apost managed by pyenv. In this case, you&aposll need to uninstall the old version of flake8 or remove the old version of Python.Open the VS Code settings explorer by going to File > Settings menu or pressing Cmd+, on macOS or Ctrl+, on Linux/Windows.
Type flake8 into the search bar and press Enter. Then paste the path to flake8 into the input box for the Python > Linting: Flake8 Path setting:

settings.json by editing the python.linting.flake8Path setting.Manage Project Dependencies With pip-tools
I only had to use pip-tools for about 5 minutes to know I needed it all the time. pip-tools helps you where you need it to and gets out of the way everywhere else. The basic usage goes like this.
Start a new Python project in a new folder:
# Create a new folder and change directories to it
mkdir ~/my-project && cd ~/my-project
# Create a new virtual environment
python3 -m venv .venv --prompt my-project
# Activate the virtual environment
source .venv/bin/activate
# Update pip
python -m pip install -U pipThen install pip-tools into the project&aposs virtual environment using pip:
python -m pip install pip-toolspip-tools through pipx, it is not yet well supported. The docs officially recommend installing pip-tools into your project&aposs environment, and I can confirm that this is the more reliable method.Your project&aposs dependencies go in a file called requirements.in. For example, the requirements.in file for a Django 3 project might look like this:
# ~/my-project/requirements.in
django<4.0You can generate a requirements.txt with fully resolved dependencies using the pip-compile command:
pip-compile --allow-unsafe --resolver=backtracking requirements.in--allow-unsafe and --resolver=backtracking options will both become the default in the next major release of pip-tools. The docs recommend passing these options to adopt the new default behavior.The requirements.txt file generated by pip-compile will look something like this:
#
# This file is autogenerated by pip-compile with Python 3.11
# by the following command:
#
# pip-compile --allow-unsafe --resolver=backtracking requirements.in
#
asgiref==3.6.0
# via django
django==3.2.16
# via -r requirements.in
pytz==2022.7.1
# via django
sqlparse==0.4.3
# via djangoNotice that there is a comment at the top of the file indicating that it was autogenerated by pip-compile (it even includes the command!) and that every version number is pinned.
I usually create a second file called dev-requirements.in for development dependencies, such as pytest and django-debug-toolbar, and even pip-tools itself:
# ~/my-project/dev-requirements.in
# Use requrements.txt as a constraint file
-c requirements.txt
django-debug-toolbar
pip-tools
pytestUsing requirements.txt as a constraint file ensures that any dependencies installed for the packages in dev-requirements.in are compatible with the package versions specified in requirements.txt.
Run pip-compile a second time to generate a dev-requirements.txt file:
pip-compile --allow-unsafe --resolver=backtracking dev-requirements.inNow for the real magic. Run pip-sync to synchronize your virtual environment with the packages in the requirements.txt and dev-requirements.txt files:
pip-sync requirements.txt dev-requirements.txtTo update or add a package, edit the appropriate .in file and then re-compile and re-sync everything.
*-requirements.inand*-requirements.txt files into version control.I often wrap all of this into a Makefile:
install:
@pip install -r requirements.txt -r dev-requirements.txt
compile:
@pip-compile --allow-unsafe --resolver=backtracking requirements.in
@pip-compile --allow-unsafe --resolver=backtracking dev-requirements.in
sync:
@pip-sync requirements.txt dev-requirements.txtCollaborators can run make install after cloning the repository to set up their environment, then run make compile && make sync as needed to keep everything synchronized.
Python dependency management tools abound.
I know many Python devs that swear by poetry or pipenv. And I know plenty that still use good ol&apos pip freeze. Personally, pipenv and poetry are too heavy-handed for my taste. pip freeze feels tedious to me. And the new pdm project looks interesting but still has a long way to go.
Call me Goldilocks, but pip-tools is the porridge that&aposs just right.
Other pipx Apps To Consider
Depending on the kind of development you do, the following packages may be useful tools to install as applications with pipx:
cookiecutterfor scaffolding projects.pre-commitfor managing pre-commit hooks.toxfor testing and task automation.buildfrontend for building Python packages.
Dig Deeper
If you write and distribute Python packages, then you need to read Dan Hillard&aposs book Publishing Python Packages.
In addition to covering how to set up, publish, maintain, and scale your package, Dane discusses setting up a professional development environment specifically for package development. It is far more versatile than the environment described in this guide.
Get instant access from Manning, or buy a print version from Amazon.

Want more like this?
One email, every Saturday, with one actionable tip.
Always less than 5 minutes of your time.