What you'll learn
Quick Answer
A virtual environment is a private folder holding its own Python interpreter and packages, so each project keeps its own dependency versions instead of sharing one global set. Create one with python -m venv venv, activate it, then install packages with pip as normal. Save the exact versions with pip freeze into requirements.txt so anyone can rebuild the same environment, and add the venv folder to .gitignore rather than committing it.
Why You Need One
Install packages globally and every project on your machine shares them. That works until two projects disagree.
Project A needs Django 3.2
Project B needs Django 5.0
pip install django==5.0 → Project A now breaksThere is no way to have both globally. This is dependency hell, and it is the reason virtual environments exist rather than being optional polish.
A virtual environment is a directory containing its own interpreter and its own site-packages. Activate it and python and pip point inside that folder, so installs affect only that project. Deactivate and you are back to the system Python.
Three problems this solves at once. Projects stop interfering with each other. You avoid installing into the system Python, which on Linux and macOS can break OS tools that depend on specific versions. And you get an exact, reproducible list of what a project needs — which is what makes "works on my machine" a solvable problem rather than an argument.
Newer Linux distributions now refuse global pip installs outright with an externally-managed-environment error, precisely to force this habit.
Creating and Activating One
venv ships with Python 3, so there is nothing to install.
# From your project folder
python -m venv venvThat creates a venv/ directory. The activation command differs by platform, which is the single most common stumbling block:
# Windows — Command Prompt
venv\Scripts\activate
# Windows — PowerShell
venv\Scripts\Activate.ps1
# macOS / Linux / Git Bash
source venv/bin/activateWhen it works, your prompt gains a prefix:
(venv) C:\projects\myapp>That prefix is the whole confirmation. No prefix means you are not in the environment and pip install is going somewhere global.
To verify properly, ask which interpreter is being used — it should point inside your project:
where python # Windows
which python # macOS / LinuxLeave with deactivate. Delete the environment by deleting the folder; there is nothing else to clean up, which is why it is safe to throw one away and rebuild when something goes wrong.
pip and requirements.txt
With the environment active, pip installs into it.
pip install requests
pip install django==4.2 # a specific version
pip list # what is installed here
pip show requests # details and dependenciesTo let someone else reproduce your setup, record the exact versions:
pip freeze > requirements.txtAnd to rebuild from it:
pip install -r requirements.txtOne habit worth adopting early: pin versions. pip freeze writes requests==2.31.0 rather than requests, so a future install gets the same version you tested against. An unpinned requirements file will one day install a new major release and break the project with no change from you.
Note that pip freeze captures everything installed, including sub-dependencies you never asked for. That is correct for reproducibility but makes the file noisy. Tools like Poetry and pipenv separate what you asked for from what came along with it — worth knowing about, though venv plus pip is entirely sufficient for learning and for most projects.
The Errors You Will Hit
PowerShell blocks activation.
Activate.ps1 cannot be loaded because running scripts is disabledWindows blocks unsigned scripts by default. Allow local ones for your user:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser"pip is not recognised". Usually Python is not on PATH. Use python -m pip instead of pip — it works whenever python does, and it also guarantees you are using the pip belonging to that interpreter.
ModuleNotFoundError for something you just installed. Almost always the environment is not active, or you installed from a different terminal. Check for the (venv) prefix, then run pip list to confirm the package is in this environment.
Your editor cannot find the packages. VS Code needs to be pointed at the interpreter: Ctrl+Shift+P, "Python: Select Interpreter", choose the one inside venv. Otherwise the terminal works while the editor underlines every import in red.
The environment stops working after moving the folder. Virtual environments contain absolute paths and do not survive being moved or renamed. Delete it and recreate — that is the intended fix, which is also why you should never commit it.
Habits Worth Forming Now
- One environment per project, created in the project folder, before installing anything.
- Add it to
.gitignore. Avenv/folder is thousands of platform-specific files. Commitrequirements.txtinstead — it is the recipe, not the meal. - Name it consistently,
venvor.venv. Editors recognise both automatically. - Regenerate
requirements.txtafter adding a dependency, and commit that change alongside the code that needs it. - Never
sudo pip install. That writes into the system Python and can break OS tooling. If a global install feels necessary, the answer is a virtual environment.
# .gitignore
venv/
.venv/
__pycache__/
*.pyc
.envThe payoff is that a new machine, a teammate, or a deployment can go from a fresh clone to a working project in two commands. That reproducibility is the entire point, and it is also what interviewers are checking when they ask how you manage dependencies.
