How To Guide

Python Virtual Environment Tutorial: venv, uv, poetry, pyenv

Set up isolated Python environments with venv, virtualenv, pipx, pyenv, poetry, and uv. Activation on macOS, Linux, and Windows PowerShell explained.

Python Virtual Environment Tutorial

A virtual environment is a self-contained folder that holds its own Python interpreter and its own site-packages. Every project you build should have one. Without isolation, installing a library for one project can break another, and global installs mix with the system Python that your OS depends on. This tutorial walks through the tools worth knowing in 2026 and shows the exact commands for macOS, Linux, and Windows PowerShell.

Why use a virtual environment?

  • Dependency isolation. Project A can pin Django 4.2 while Project B uses Django 5.1.
  • Reproducibility. A locked list of packages means teammates and CI install identical versions.
  • Safety. You never run sudo pip install against system Python, which can corrupt OS tooling.

The tools

venv (built in since Python 3.3)

The standard library module. Zero install, always available. This is the right default for scripts and small projects.

python -m venv .venv

virtualenv (older, third-party)

Predates venv. It is faster to create environments and supports older Python versions, but for modern work venv covers 95% of use cases. Install with pip install virtualenv, then virtualenv .venv.

pipx (for CLI tools)

When you want a command-line tool like black, httpie, or ruff available everywhere but each in its own isolated environment, use pipx. It is not for project dependencies.

pipx install ruff
pipx install httpie

pyenv (Python version manager)

pyenv installs and switches between multiple Python versions on the same machine. Combine it with venv or uv to pick the interpreter, then create the environment.

pyenv install 3.12.5
pyenv local 3.12.5
python -m venv .venv

On Windows use pyenv-win.

Poetry (project + venv + lockfile)

Poetry manages pyproject.toml, resolves dependencies, writes a poetry.lock, and creates a virtual environment for you. It is a good fit for libraries you publish to PyPI.

poetry new myproject
cd myproject
poetry add requests
poetry install
poetry run python app.py

uv (fast, Rust-based)

uv from Astral is a Rust-written package and project manager that has become the fastest-growing option. It creates environments, resolves dependencies, and locks them in one tool, and it is dramatically faster than pip. Install it with pipx install uv or the standalone installer, then:

uv venv                # create .venv
uv pip install requests
uv init                # start a project with pyproject.toml
uv add fastapi
uv run python app.py

Activating on each OS

Activation puts the environment's bin/Scripts folder at the front of PATH and usually prefixes your shell prompt with (.venv).

macOS and Linux (bash, zsh)

source .venv/bin/activate
deactivate

Windows PowerShell

.venv\Scripts\Activate.ps1

If PowerShell blocks the script with an execution policy error, run once:

Set-ExecutionPolicy -Scope CurrentUser RemoteSigned

Windows cmd.exe

.venv\Scripts\activate.bat

requirements.txt vs pyproject.toml

requirements.txt is a flat list of pinned packages, generated with pip freeze > requirements.txt and restored with pip install -r requirements.txt. Simple, universally understood, but has no separation between direct and transitive dependencies.

pyproject.toml (PEP 621) is the modern manifest. It declares your project metadata and direct dependencies. Tools like poetry, uv, and hatch pair it with a lockfile (poetry.lock, uv.lock) for exact reproducibility. Prefer pyproject.toml for new projects.

Common issues

  • Prompt does not change. You may have opened a new terminal or activated the wrong path. Confirm with which python (macOS/Linux) or Get-Command python (PowerShell). It should point inside .venv.
  • activate.bat vs Activate.ps1. These are not interchangeable. Use the one that matches your shell.
  • Wrong Python version inside venv. The environment inherits from whichever interpreter created it. Use python3.12 -m venv .venv or set pyenv local first.
  • .gitignore. Never commit the environment itself. Add these lines:
    .venv/
    venv/
    __pycache__/
    *.pyc
    Commit requirements.txt or pyproject.toml plus the lockfile instead.
  • VS Code not detecting the venv. Open the command palette, run "Python: Select Interpreter", and pick the one inside .venv.

A quick recommendation

Starting a new project today? Try uv init. Maintaining an existing project with a requirements.txt? Stick with python -m venv .venv and pip. Publishing a library? Poetry is still an excellent choice. All three work fine alongside pyenv when you need to juggle Python versions.

python venv virtualenv uv python poetry pyenv pipx requirements.txt pyproject.toml

Explore 300+ Free Tools

Utilko has tools for developers, writers, designers, students, and everyday users — all free, all browser-based.