← all articles
environment setup

Python Environment Setup

pyenv for version management, virtual environments for dependency isolation — the two habits that prevent almost every Python setup headache.

3 min read·July 9, 2026

Nearly every confusing Python bug report — "works on my machine", pip install clobbering unrelated packages, a script silently using the wrong interpreter — traces back to skipping two habits: managing Python versions explicitly, and never installing packages outside a virtual environment. This guide sets both up.

Don't use the system Python

macOS and most Linux distros ship a Python for their own internal tooling. It's tempting to pip install straight into it, but that's exactly how you end up breaking OS scripts or fighting permission errors. Treat the system Python as off-limits and manage your own versions with pyenv.

Install pyenv

macOS:

brew install pyenv

Linux:

curl https://pyenv.run | bash

Either way, add this to your ~/.zshrc or ~/.bashrc:

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

Restart your terminal and confirm:

pyenv --version

Windows users: use pyenv-win, or better, run this whole guide inside WSL2 — the Python tooling ecosystem assumes a POSIX shell almost as universally as the Node ecosystem does.

warning

On Linux, pyenv builds Python from source, so it needs build tools and headers installed first (build-essential, libssl-dev, zlib1g-dev, and a handful of others — the pyenv wiki's "suggested build environment" page has the exact list per distro). Skipping this step is the single most common pyenv install failure.

Install a Python version

pyenv install 3.12
pyenv global 3.12

Verify:

python --version
pip --version

Pin the version per project

Inside a project directory:

pyenv local 3.12

This drops a .python-version file, which pyenv reads automatically — cd into that directory and python resolves to 3.12 without touching your global setting.

Always use a virtual environment

A virtual environment gives each project its own isolated set of installed packages, so pip install in one project can never break another. The built-in venv module is enough for most projects:

python -m venv .venv
source .venv/bin/activate

Your shell prompt will show (.venv) while it's active. Install project dependencies inside the activated environment:

pip install -r requirements.txt

Freeze what's installed back into that file as you add packages:

pip freeze > requirements.txt

Deactivate when you're done:

deactivate
tip

If a project's dependency list is growing complex — version conflicts, dev-only vs. production dependencies, lockfiles — look at Poetry or uv instead of hand-managing requirements.txt. Both wrap pyenv-style version management and virtual envs into one tool with a lockfile, similar to what package-lock.json does for Node.

Common gotchas

warning

pyenv install 3.12 fails partway through compiling. This is almost always a missing build dependency (see the callout above), not a pyenv bug. Read the actual error near the top of the output — it usually names the missing library directly.

warning

python still resolves to /usr/bin/python3 after installing pyenv. The eval "$(pyenv init -)" line has to run after your PATH is set, and it has to actually be in the shell config file your terminal loads. Run type python — if it doesn't point into ~/.pyenv/shims/python, the init line isn't taking effect.

Once pyenv and a virtual environment are both second nature, "it works on my machine" stops being a Python problem — every project carries its own exact interpreter version and dependency set with it.