Python Virtual Environments: Why You Need Them and How to Create Them
1. The Problem
I installed requests version 2.28.0 for my Project A. Then I started Project B, which needed requests 2.31.0. I ran pip install requests==2.31.0 and suddenly Project A broke:
ImportError: cannot import name 'default_headers' from 'requests.adapters'This is the classic dependency conflict problem. When you install packages globally, different projects compete for the same package versions. One project wins, others break.
2. Why This Happens
The root cause is simple: Python by default installs packages to a single global location. All projects share this same pool of packages.
+------------------+| System Python | <-- Single global package pool+------------------+ | v+---------------------------+| requests==2.31.0 | <-- Latest version wins| flask==3.0.0 || numpy==1.24.0 || ... (100+ packages) |+---------------------------+ | +----+----+ | |Project A Project B(needs (needs2.28.0) 2.31.0) ^ ^ | | +---------+---------+ | CONFLICT!The consequences are predictable:
- Version conflicts: Different projects need different versions of the same package
- Deployment failures: Your code works locally but fails on another machine
- Permission issues: Global installation may require admin privileges
- Debugging nightmares: Which package caused the problem? Hard to tell when everything is mixed together
3. The Solution: Virtual Environments
A virtual environment is an isolated Python installation with its own package directory. Each project gets its own sandbox.
+------------------+| System Python | <-- Clean, untouched+------------------+
+------------------+ +------------------+| Project A Env | | Project B Env |+------------------+ +------------------+| requests==2.28.0 | | requests==2.31.0 || flask==2.2.0 | | flask==3.0.0 || pandas==1.5.0 | | numpy==1.26.0 |+------------------+ +------------------+ | | v v Project A Project B (works!) (works!)Each environment is completely independent. Project A’s requests 2.28.0 stays in its sandbox. Project B’s requests 2.31.0 stays in another. No conflicts.
4. Step-by-Step Setup
4.1 Create the Virtual Environment
python -m venv myproject_envThis creates a directory myproject_env containing a standalone Python installation.
4.2 Activate the Environment
On Unix/macOS:
source myproject_env/bin/activateOn Windows:
myproject_env\Scripts\activateAfter activation, your shell prompt changes:
# Before activation$ python script.py
# After activation(myproject_env) $ python script.pyThe (myproject_env) prefix confirms you’re inside the virtual environment.
4.3 Verify Activation
I always double-check I’m in the right environment before installing anything:
# Unix/macOSwhich python# Output: /path/to/myproject_env/bin/python
# Windowswhere python# Output: C:\path\to\myproject_env\Scripts\python.exeIf the path points to your virtual environment directory, you’re good.
4.4 Install Packages
pip install requests==2.31.0 flask==3.0.0 pandasAll packages install into the virtual environment, not globally.
4.5 Save Dependencies
pip freeze > requirements.txtThis creates a requirements.txt file with exact versions:
requests==2.31.0flask==3.0.0pandas==2.0.34.6 Recreate Environment Later
On another machine, or after deleting the environment:
python -m venv myproject_envsource myproject_env/bin/activatepip install -r requirements.txtYour environment is perfectly reproduced.
4.7 Deactivate
deactivateYou exit the virtual environment and return to system Python.
5. Common Mistakes I’ve Made
Mistake 1: Installing Before Activating
# WRONG - installs globallypip install requests
# RIGHT - activate firstsource myproject_env/bin/activatepip install requestsI’ve done this many times. The package goes to global Python, and my project still fails with import errors.
Mistake 2: Not Pinning Versions
# WRONG - version could changepip install requests
# RIGHT - pin the versionpip install requests==2.31.0Without version pinning, pip freeze captures whatever version was current. Months later, pip install -r requirements.txt might get a different version if the lock file wasn’t generated properly.
Mistake 3: Using Legacy virtualenv
# OLD WAY (legacy)virtualenv myenv
# NEW WAY (standard library, Python 3.3+)python -m venv myenvvirtualenv is a third-party tool. venv is built into Python since 3.3. For new projects, use venv.
Mistake 4: Ignoring requirements.txt
I skipped pip freeze > requirements.txt on a project once. When my teammate tried to run it, they spent two hours figuring out which packages were needed.
6. How to Detect If You’re in a Virtual Environment
Sometimes I forget whether I’m in a venv. Here’s a quick Python check:
import sys
def in_virtualenv(): return hasattr(sys, 'real_prefix') or ( hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix )
if in_virtualenv(): print(f"Inside virtual environment: {sys.prefix}")else: print("Using system Python")Running this tells you immediately where you stand.
7. venv vs virtualenv vs conda
| Feature | venv | virtualenv | conda ||------------------|----------------|----------------|----------------|| Built-in | Yes (Python 3.3+) | No (pip install) | No (separate) || Python versions | Same as system | Different versions | Different versions || Non-Python deps | No | No | Yes (C libs, etc) || Speed | Fast | Medium | Medium || Use case | Standard Python projects | Legacy projects | Scientific computing |For most Python projects, venv is the right choice. It’s standard, lightweight, and built into Python.
8. Summary
Virtual environments solve the dependency conflict problem by isolating each project’s packages. The workflow is simple:
python -m venv myenv- createsource myenv/bin/activate- activatepip install packages- installpip freeze > requirements.txt- savedeactivate- exit
This pattern is standard practice for all professional Python development. Skip it, and you’ll waste hours debugging mysterious import errors.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments