Python Virtual Environments and pip: A Practical Guide
Imagine you're a carpenter working on two different projects. One needs tiny finishing nails and the other needs heavy-duty bolts. You wouldn't dump all your hardware into one toolbox — you'd have separate toolboxes so the right parts are always ready for the right job.
Python virtual environments work the same way. Each project gets its own isolated toolbox of packages and dependencies. This means Project A can use version 1.0 of a library while Project B uses version 2.0, and they'll never interfere with each other.
In this tutorial, you'll learn why virtual environments matter, how to create and use them, and how to manage packages with pip and requirements.txt.
Why Do You Need Virtual Environments?
Without virtual environments, every package you install goes into one global Python installation. This seems fine at first, but it quickly becomes a problem.
Imagine you built a website last year using requests version 2.25. Now you're starting a new project that needs requests version 2.31. If you upgrade globally, your old website might break. If you don't upgrade, your new project can't use the latest features.
How Do You Create and Activate a Virtual Environment?
Python 3 ships with a built-in module called venv that creates virtual environments. No extra installation needed — it's ready to go.
Here's the workflow: you create the environment once, then activate it every time you work on that project. When activated, any packages you install go only into that environment.
When the environment is active, you'll see its name in parentheses at the start of your terminal prompt. This is your visual confirmation that you're working inside the isolated environment.
How Do You Install Packages with pip?
pip is Python's package installer. It downloads packages from PyPI (the Python Package Index) — a massive online catalog with over 500,000 packages. Think of PyPI as an app store for Python.
Once your virtual environment is active, every pip install command puts packages only into that environment. Here are the essential commands:
What Is requirements.txt and Why Does It Matter?
Imagine handing your project to a teammate. They need to install every package your project depends on. Telling them "just install requests and flask and maybe pandas" is messy and error-prone.
A requirements.txt file is a simple text file that lists every package and its exact version. Your teammate just runs one command and everything gets installed automatically.
Notice that pip freeze also lists transitive dependencies — packages that your packages depend on. For example, flask needs werkzeug, so werkzeug shows up even though you didn't install it directly.
How Do You Manage Dependencies Across Environments?
Real projects often have different dependencies for different situations. Your development machine might need testing tools and linters, but your production server only needs the core packages.
The -r requirements.txt line inside requirements-dev.txt means "include everything from the base file too." This way, developers get all the core packages plus development tools, while production only installs the essentials.
Practice Exercises
These exercises test your understanding of virtual environments, pip, and dependency management. Since we're in a browser, we'll simulate these concepts with Python code.
Write a function called parse_requirements(text) that takes a string representing a requirements.txt file (one package per line in the format name==version). Return a dictionary mapping package names to their versions. Ignore empty lines and lines starting with #.
The code below simulates a dependency resolver that checks if installed packages satisfy requirements. There are bugs causing incorrect output. Fix them so the resolver correctly identifies which requirements are met and which are not.
Read the code carefully and predict the output. The code simulates checking which virtual environment is active and what packages are available.
Create a class called VenvManager that simulates managing virtual environments:
__init__(): Initialize with an empty dictionary envs and set active to Nonecreate(name): Add an environment with name as key and an empty list as value. Print Created: nameactivate(name): Set active to name if it exists. Print Activated: name. If it doesn't exist, print Error: name not foundinstall(package): Append package to the active environment's list. Print Installed: package. If no environment is active, print Error: no active environmentlist_packages(): Print each package in the active environment, one per line. If no environment is active, print Error: no active environment. If the environment is empty, print No packages installed