- Published on
Python Virtual Environments - The Right Way to Manage Dependencies
- Authors

- Name
- Sanjeev Sharma
- @webcoderspeed1
Introduction
Every Python developer has been there: you install a package for one project, it breaks another project. Virtual environments solve this problem by giving each project its own isolated Python environment.
In 2026, there's also the blazing-fast uv tool to modernize your workflow.
- What is a Virtual Environment?
- Creating and Using venv
- Requirements Files
- Modern Approach: uv (Ultra-fast Package Manager)
- Project Structure Best Practices
- Managing Different Python Versions with pyenv
- Environment Variables with .env
- Conclusion
What is a Virtual Environment?
A virtual environment is an isolated Python installation with its own packages. Changes to one venv don't affect others or your system Python.
System Python → has package A v1.0
Project 1 venv → has package A v1.0, package B v2.5
Project 2 venv → has package A v3.0, package C v1.2
Each project is completely isolated.
Creating and Using venv
# Create a virtual environment
python -m venv venv
# Activate it
source venv/bin/activate # macOS/Linux
venv\Scripts\activate.bat # Windows CMD
venv\Scripts\Activate.ps1 # Windows PowerShell
# Your prompt shows (venv) when active
(venv) $
# Install packages (only affects this venv)
pip install requests flask
# Deactivate
deactivate
Requirements Files
# Save current environment
pip freeze > requirements.txt
# Install from requirements.txt (on another machine/in CI)
pip install -r requirements.txt
Flask==3.0.0
requests==2.31.0
SQLAlchemy==2.0.23
python-dotenv==1.0.0
Modern Approach: uv (Ultra-fast Package Manager)
uv is a new Python package manager written in Rust — 10-100x faster than pip:
# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# Create a project with uv
uv init my-project
cd my-project
# Add dependencies
uv add requests flask pandas
# Run your script (auto-installs dependencies)
uv run main.py
# Create a virtual environment explicitly
uv venv
# Sync dependencies from pyproject.toml
uv sync
uv manages everything in pyproject.toml — the modern Python standard:
[project]
name = "my-project"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
"requests>=2.31.0",
"flask>=3.0.0",
"pandas>=2.1.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.0.0",
"black>=23.0.0",
"mypy>=1.0.0",
]
Project Structure Best Practices
my-project/
├── venv/ ← Virtual environment (never commit!)
├── src/
│ └── my_project/
│ ├── __init__.py
│ └── main.py
├── tests/
│ └── test_main.py
├── .gitignore ← Include venv/ here
├── pyproject.toml ← Modern: replaces setup.py + requirements.txt
└── README.md
venv/
.venv/
__pycache__/
*.pyc
.env
*.egg-info/
dist/
build/
Managing Different Python Versions with pyenv
# Install pyenv (macOS/Linux)
brew install pyenv
# Install a specific Python version
pyenv install 3.12.0
pyenv install 3.11.5
# Set global default
pyenv global 3.12.0
# Set project-specific version (creates .python-version file)
pyenv local 3.11.5
# List installed versions
pyenv versions
Environment Variables with .env
pip install python-dotenv
from dotenv import load_dotenv
import os
load_dotenv() # Load .env file
DATABASE_URL = os.getenv('DATABASE_URL')
SECRET_KEY = os.getenv('SECRET_KEY')
DEBUG = os.getenv('DEBUG', 'false').lower() == 'true'
DATABASE_URL=postgresql://user:pass@localhost/mydb
SECRET_KEY=super-secret-key-change-this
DEBUG=true
Conclusion
Virtual environments are non-negotiable for serious Python development. Use venv for simplicity, uv for speed, and pyenv when you need multiple Python versions. Always commit your requirements.txt or pyproject.toml, never your venv/ folder, and keep your .env in .gitignore. These habits will save you from countless "it works on my machine" headaches.