I'm using uv now. I'm also still using pyenv, but uv may replace the need for this in the future.
Setting up a development environment for Python can be a bit confusing, mainly stemming from the fact that there are multiple competing standards for package management.
Compared with JavaScript and Node.js, which indeed have several different popular package managers such as npm
, yarn
, and pnpm
, they at least all agree on a common manifest format (package.json
) and they are largely all interoperable with each other. In addition, it's very clear to new JS developers that npm
is where you ought to start.
This is not the case with Python, where there are multiple competing manifest formats (requirements.txt
, Pipfile
, pyproject.toml
), interoperability is hit and miss, and it's not clear where to start because the official PEPs are somewhat conflicting and the Python Packaging Authority (PyPA) doesn't take a strong stance on the issue either.
pip
, which usesrequirements.txt
, is the most official and is in the standard lib. But, it's lacking in features you might expect to be built in.pyproject.toml
is also official and you see it mentioned in more recently approved PEPs. This format has been adopted by some newer, but decidedly unofficial, tools.- Then there is
pipenv
and thePipfile
, which isn’t enshrined in the PEPs, but it’s quasi-official because it’s maintained by PyPA.pipenv
seems to have all the community support for the future direction of Python package management.
Those are the main contenders in my opinion, but there’s half a dozen others such as Poetry
, Rye
, and pdm
.
This guide will walk you through setting up a Python development environment using pyenv
, pipx
, and pipenv
. This is the toolchain that I have settled on after trying out several different options. pipenv
was chosen as the package manager for it's strong community support, endorsement by PyPA, and it's robust feature set, such as built in support for creating isolated virtual environments for each project, ability to generate lockfiles and install dev dependencies, and the fact that transitive dependencies are not intermingled with your project dependencies in the manifest file.
- If you commonly work on other people's projects, you will likely need to be familiar with other workflows and may need to install additional tools.
- This guide is intended to be a solid starting point for application developers. No consideration has been given to library authors and/or the tools and workflows necessary for publishing packages.
pyenv
- Install and switch between multiple different versions of Pythonpipx
- Work with Python global cli tools. Similar tonpx
.pip
could also be used for this, butpipx
is better because it creates an isolated environment for each cli tool.pipenv
- Create virtual environments and manage project dependencies usingPipfile
andPipfile.lock
Note 1: This guide assumes that you already have Homebrew and Xcode command line tools installed. If not, install them first.
Note 2: This guide assumes you are using the fish shell. If you are using a different shell, consult the pyenv docs for instructions on how to configure your shell.
-
Install pyenv
Install with brew...
brew install pyenv
Configure fish shell...
set -Ux PYENV_ROOT $HOME/.pyenv fish_add_path $PYENV_ROOT/bin
Reload fish shell for PATH changes to take effect. Then, add this to ~/.config/fish/config.fish...
pyenv init - | source
Install dependencies required by pyenv...
brew install openssl readline sqlite3 xz zlib tcl-tk
-
Install python using pyenv
List available versions...
pyenv install --list
Install a specific version...
pyenv install 3.11.6
Set the global version...
pyenv global 3.11.6
-
Install pipx using brew (installing with pip is also an option)
brew install pipx pipx ensurepath
-
Install pipenv using pipx
pipx install pipenv
-
Create a new project directory and initialize git
mkdir my-project cd my-project git init touch .gitignore
-
Set the python version for the project
pyenv install 3.11.6 (if not already installed) pyenv local 3.11.6
-
Create a virtual environment for the project
Note: If you would prefer that the virtual environment is created locally to the project, you can set the environment variable
PIPENV_VENV_IN_PROJECT=1
. Be sure to add.venv
to your.gitignore
file. This is somewhat of an underdocumented feature.pipenv install
-
Activate the virtual environment. This must be done for each new shell session.
pipenv shell
Alternatively, you can run commands in the virtual environment without activating it...
pipenv run python app.py
-
Install project dependencies
pipenv install flask or pipenv install flask==3.0.0
I think you need to manually edit the Pipfile and rerun
pipenv install
if you want a flexible version range. The cli doesn't seem to support it.flask = ">=3.0,<4.0"
If you just cloned a project, you can install all dependencies from the Pipfile...
pipenv install
Or, if you also want dev dependencies...
pipenv install --dev
If you like small focused tools and you like using official things from the standard lib, this might be more to your taste.
pyenv
- samepipx
- samepip
- Install project dependencies usingrequirements.txt
and, optionally,dev-requirements.txt
. Comes packaged with modern python installations.venv
- Create isolated virtual environments for your projects. Comes packaged with modern python installations.pip-tools
- A community project that provides a standard convention for adding lockfiles to your Python workflow.