Skip to content

Python Project Environment Setup

First PublishedByAtif Alam

This page walks through setting up a new Python project on macOS: check or install Python, create an isolated environment, install dependencies, and pin versions when you need more than one interpreter.

Guides elsewhere in this library often use the standard library only; use this page when you need third-party packages or a pinned Python version.

Terminal window
python3 --version
which python3

macOS may ship a system python3. That is fine for a quick check, but avoid using it as your only interpreter for development — system Python is meant for the OS, not your projects.

If you installed Python with Homebrew (brew install [email protected]), which python3 may point at Homebrew’s binary instead.

uv installs Python versions, creates virtual environments, and manages packages in one tool.

Terminal window
# Option A: Homebrew (same pattern as other macOS guides in this library)
brew install uv
# Option B: official installer
curl -LsSf https://astral.sh/uv/install.sh | sh
uv --version
uv python install 3.12
uv python list

See the uv documentation for advanced options.

Terminal window
brew install [email protected]
python3.12 --version

Use this when you want a standalone interpreter without uv. You still create virtual environments with python3.12 -m venv (see below).

You may need Python 3.11 for one repo and 3.12 for another. Two common approaches on a Mac:

Concernuvpyenv
Install/switch Python versionsuv python install, uv python pin, .python-versionpyenv install, pyenv local / pyenv global
Virtual env + packagesBuilt-in (uv venv, uv add, uv sync)Needs venv or a plugin such as pyenv-virtualenv
Speed / modern workflowFast; one tool for versions and depsMature; shell shims; common on existing teams
Best whenNew projects, greenfield Mac setupTeam already standardized on pyenv, or global shim switching across many tools

uv can manage Python versions for most new workflows — you do not need pyenv if you adopt uv end-to-end.

pyenv remains valid when your team or dotfiles already rely on it. uv and pyenv can coexist: pyenv selects which python runs in your shell; uv still speeds up installs inside a project.

Per-project pinning: uv python pin 3.12 writes a .python-version file. pyenv uses the same filename.

Do not let both tools fight over .python-version without knowing which one owns it in a given repo.

asdf fills a similar niche to pyenv (multiple runtimes, one version file). The same advice applies: pick one version manager per project.

Terminal window
mkdir myapp && cd myapp
uv init --python 3.12
uv venv
source .venv/bin/activate
uv add requests
uv run python -c "import requests; print(requests.__version__)"

Expected layout:

myapp/
pyproject.toml
.venv/
main.py # or src/ layout for larger apps

Add to .gitignore at minimum:

.venv/
__pycache__/
*.pyc

Some teams commit .python-version; others gitignore it. Pick one convention per repo.

For teams that require pip and requirements.txt:

Terminal window
mkdir myapp && cd myapp
python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install requests
pip freeze > requirements.txt

pip installs packages only; it does not install Python interpreters. Use uv, Homebrew, or pyenv when you need another Python version.

Teams that pin dependencies heavily sometimes use requirements.in with pip-tools; that is optional here.

Most Python tutorials and docs online assume pip. If you set up with uv, use this table when you follow those instructions.

Following a tutorial that says pip install …? Use the table below — you usually do not need to install pip separately.

You See Online (pip)With uv (Recommended)Notes
pip install requestsuv add requestsUpdates pyproject.toml and lockfile when using the uv init workflow
pip install requests==2.31.0uv add 'requests==2.31.0'Quote versions that contain shell metacharacters
pip install -r requirements.txtuv pip install -r requirements.txtDrop-in when a tutorial ships a requirements file
pip install -e .uv pip install -e . or uv syncEditable install for local packages
python script.pyuv run python script.pyWorks without activating .venv
pip freeze > requirements.txtPrefer uv add and a committed lockfileuv export can emit requirements-style output if needed
pip install --upgrade pipSkip — uv manages toolingNot needed in a uv-managed project

Two uv modes:

  1. uv add — project-native. Use when you started with uv init and want dependencies tracked in pyproject.toml.
  2. uv pip install — pip-compatible shim. Use when copying commands verbatim from older docs or requirements.txt-based tutorials.

If a tutorial mixes system Python and pip, stop and use your project .venv (or uv run) instead — do not install packages into the macOS system interpreter.

TaskCommand
Activate envsource .venv/bin/activate
Deactivatedeactivate
Add a dependency (uv project)uv add package-name
Add from an old tutorialuv pip install package-name — see Translating Online pip Commands to uv
Run without activatinguv run python script.py

With .venv activated:

Terminal window
which python
python --version
python -c "import sys; print(sys.prefix)"

sys.prefix should point inside your project’s .venv directory, not /usr or a system path.

  • On macOS, check python3 --version first; avoid developing against the system interpreter alone.
  • uv is the recommended path: install Python versions, create .venv, and manage deps with uv add or uv pip install.
  • pyenv (or asdf) still fits teams already on those tools; uv can manage versions without them for new projects.
  • Online docs say pip install — translate with the table above (uv add vs uv pip install).
  • Confirm your active interpreter with which python and sys.prefix inside .venv.