Python Virtual Environments Explained
A Python virtual environment is an isolated place to install dependencies for one project. That is the practical definition. Without virtual environments, every Python package you install can end up in the same global Python installation. That gets messy quickly. One project may need Django. Another may need FastAPI. One may need an older package version. Another may need a newer one. If all of those packages live together globally, projects start affecting each other. A virtual environment keeps each project separate.
The Mental Model
Think of a virtual environment as a private toolbox for one project. The project gets its own:
- Python executable link
- installed packages
- command line scripts
- dependency state If you install Django inside one virtual environment, that does not mean Django is installed for every Python project on your machine. That isolation is the whole point. ```plain text project-a/ .venv/ app.py
project-b/ .venv/ app.py
Each project has its own \`.venv\`.
## Creating a Virtual Environment
Python includes the \`venv\` module.
From inside your project directory:
```bash
python3 -m venv .venv
This creates a `.venv` folder. On macOS or Linux, activate it with:
source .venv/bin/activate
Once activated, your shell prompt may change to show the environment name. You can check which Python is being used:
which python
It should point somewhere inside your project: ```plain text /path/to/project/.venv/bin/python
## Installing Packages
After activating the environment, install packages with \`pip\`:
```bash
pip install django
pip install requests
Those packages go into the virtual environment, not your global Python installation. You can inspect installed packages:
pip list
Or freeze exact versions:
pip freeze
For many simple projects, you will see a `requirements.txt` file:
pip freeze > requirements.txt
Another machine can install the same dependencies:
pip install -r requirements.txt
Many newer projects use `pyproject.toml` instead, especially when using tools like Poetry, Hatch, uv, or PDM. The same core idea still applies: the project should declare its dependencies somewhere reproducible.
Why `.venv` Usually Stays Out of Git
The virtual environment folder itself should usually not be committed. It contains installed packages, generated files, and machine-specific paths. Instead, commit the dependency file: ```plain text requirements.txt pyproject.toml poetry.lock uv.lock
Then each machine can recreate the environment.
Your \`.gitignore\` will often include:
```plain text
.venv/
That keeps the repository focused on source code and dependency declarations, not local install output.
Deactivating the Environment
When you are done, you can deactivate:
deactivate
This returns your shell to the normal Python environment. In practice, I do not think about this too much. I usually open a terminal in a project, activate the environment, work, and close the terminal when I am done.
Common Mistakes
Mistake 1: Installing packages before activating the environment
If you run `pip install` before activating `.venv`, you may install packages somewhere else. Check with:
which python
which pip
Both should point inside `.venv`.
Mistake 2: Committing the `.venv` folder
The environment is build output. Commit the dependency files, not the installed environment.
Mistake 3: Depending on global packages
If a project works only because you installed something globally months ago, it will fail on another machine. A new checkout should be able to recreate its dependencies from the repository instructions.
Where This Shows Up in Real Projects
Virtual environments matter as soon as you move beyond one-off scripts. For a Django site, the virtual environment contains Django and the packages the project needs to run. For a static site generator, it may contain Markdown parsers, image tools, and API clients. For automation scripts, it may contain SDKs for services like Notion, GitHub, or Google APIs. The habit is the same:
- Create `.venv`
- Activate it
- Install dependencies
- Record dependencies
- Keep `.venv` out of Git That habit makes projects much easier to move between machines.
Key Takeaways
- A virtual environment isolates Python dependencies for one project.
- Use `python3 -m venv .venv` to create one.
- Activate it before installing packages.
- Commit dependency files, not the `.venv` folder.
A project should be reproducible on a second machine without relying on global packages.
Related Articles
How to Structure a Python Project
- Django Project Structure Explained
- Setting Up a Mac for Development