Virtual environments are lightweight, isolated Python environments that keep your project dependencies separate from your system Python and from other projects. They make your projects reproducible, prevent package version conflicts, and keep your development environment clean.
What is a Python virtual environment?
A virtual environment (venv) is a directory that contains a specific Python interpreter and a local copy of the site-packages directory. When you activate a venv, commands like python and pip point to the interpreter and package installer inside that directory instead of the system-wide ones.
Why this matters:
- Different projects can require different versions of the same package (for example, Django 2.x vs 4.x). venvs avoid conflicts.
- You can test against multiple Python versions without polluting the global environment.
- Deploying becomes easier when you freeze dependencies and recreate the same environment.
Quick terminology
- venv: Built-in module in Python 3 (recommended and simple).
- virtualenv: Popular third-party tool compatible with older Python versions — sometimes faster and with extra features.
- pipx: Installs and runs Python CLI tools in isolated environments, good for global CLIs.
- Poetry / Pipenv: Higher-level tools that manage venvs, dependency resolution, and packaging.
Create a virtual environment (venv)
Create a venv in your project folder and activate it (recommended name: .venv or venv):
# Create the venv
python -m venv .venv
# Activate on macOS / Linux (bash/zsh)
source .venv/bin/activate
# Activate on Windows (PowerShell)
.\.venv\Scripts\Activate.ps1
# Deactivate
deactivate
Notes:
- Using a dot-prefixed directory like .venv keeps it hidden in many file explorers.
- You can use any directory name; just be consistent and add it to .gitignore.
Installing packages and freezing requirements
Inside an activated venv:
# Install packages
pip install requests flask
# Show installed packages
pip list
# Freeze to requirements.txt for reproducible installs
pip freeze > requirements.txt
# Recreate environment on another machine
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
Using virtualenv (older or specific needs)
virtualenv gives a similar workflow and works with older Pythons:
pip install virtualenv
virtualenv venv-env
source venv-env/bin/activate
pipx — install CLI tools globally but isolated
Use pipx to install command-line tools without polluting your main environment:
pip install --user pipx
python -m pipx ensurepath
pipx install black
# Run black anywhere
black my_file.py
pipx installs each tool into its own isolated environment and places shims on your PATH.
Poetry — dependency management + venv management
Poetry automates dependency resolution and creates project venvs (recommended for apps/libs):
# Install poetry (one-liner; follow official docs for latest)
curl -sSL https://install.python-poetry.org | python3 -
# Create new project
poetry new myproj
cd myproj
# Let Poetry create and manage the venv, add deps
poetry add requests
poetry shell # spawn a shell in the venv
poetry run python -m myproj
Poetry uses pyproject.toml for config and makes publishing easier.
Best practices for projects
- Use a project-local venv (e.g., .venv) and add it to .gitignore.
- Pin direct dependencies in requirements.txt or use pyproject.lock (Poetry). Don’t commit large site-packages.
- Prefer python -m venv .venv over system package managers.
- Use virtual environments for both development and CI to ensure parity.
- For quick CLI tools, prefer pipx.
Example .gitignore snippet:
.venv/
venv/
__pycache__/
*.pyc
Working with multiple Python versions
Use pyenv (or system-installed interpreters) to install multiple Python versions, then create venvs from each version:
# Example with a python3.10 interpreter already installed
python3.10 -m venv .venv-py310
source .venv-py310/bin/activate
python --version
CI tips (GitHub Actions example)
A minimal workflow to reproduce environment using requirements.txt:
name: Python CI
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
- name: Run tests
run: |
source .venv/bin/activate
pytest
(Use the actions/cache action to cache pip downloads for faster builds.)
Troubleshooting
- “pip not found” after activation: ensure you activated the venv in the same shell; on Windows prefer PowerShell activation or use .\.venv\Scripts\python -m pip.
- Wrong Python version: create the venv with the desired python executable (python3.9 -m venv .venv).
- Dependencies missing in production: make sure you froze exact versions and installed them in the deployment environment.
When not to use virtual environments
- Single short-lived script executed once on your machine may not need a venv.
- If you’re using system packages intentionally (e.g., system-wide daemon with distro-managed packages), coordinate with system package manager instead.
Short checklist before shipping a Python project
- Add .venv/ (or chosen venv folder) to .gitignore
- Commit requirements.txt or poetry.lock / pyproject.toml
- Document how to create and activate the venv in README
- Use pipx for global CLIs and Poetry for app dependency management
Summary
Virtual environments are a fundamental tool for clean, reproducible Python development. Use python -m venv for simple projects, pipx for isolated CLIs, and Poetry if you want an all-in-one dependency and packaging workflow. Activate the venv, install packages, freeze your dependencies, and you’ll avoid “it works on my machine” problems.
