RizTech Academy logo
RizTech Academy
Modules, Packages and EnvironmentsLesson 3 of 520 min

Virtual environments, and why they matter

This lesson explains the ModuleNotFoundError from module 6 — the one where you definitely installed the package and Python insists it is not there — and the python3-venv line from the installation lesson.

It is also the single habit that separates people whose projects keep working from people whose projects mysteriously stop.

The problem

Install a package without a virtual environment and it goes into your system Python, shared by everything.

Now imagine two projects:

  • Project A, finished last year, uses Django 4.2
  • Project B, starting today, needs Django 5.1

Install Django 5.1 and project A breaks, because there is one Django and both projects share it. Your options become upgrading project A — work you did not plan and may not be able to test — or not starting project B.

It gets worse with indirect dependencies. Package X needs requests 2.28; package Y needs 2.31. Installing Y silently upgrades requests and breaks X, with an error that mentions neither.

And it is not reproducible. "Works on my machine" usually means your machine has forty packages installed over two years, and a colleague's does not.

The solution

A virtual environment is a private folder holding its own Python and its own packages. Each project gets one. Installing into one cannot affect another.

Creating and using one

cd my-project
python -m venv .venv

That creates a .venv folder. python -m venv rather than a venv command — the -m form runs the module belonging to the Python you invoked, which guarantees the environment is built from the interpreter you meant.

On Ubuntu this is where you need the python3-venv package from the installation lesson. If it errors, that is the fix.

Then activate it:

source .venv/bin/activate

On Windows PowerShell:

.venv\Scripts\Activate.ps1

Your prompt changes to show the environment name:

(.venv) priya@laptop:~/my-project$

That prefix is how you know it is active. No prefix, no environment — and pip install then goes somewhere global.

To leave:

deactivate

Checking which Python you are on

The diagnostic worth memorising, from module 2:

python -c "import sys; print(sys.executable)"

Active, it prints something inside .venv. Inactive, it prints your system Python. When a package is "not found" despite being installed, run this first — it answers the question immediately.

pip list shows what is installed in the current environment. A freshly created one has almost nothing, which is the point.

The ModuleNotFoundError from module 6

Now it makes sense. The usual sequence:

  1. You install a package in one terminal
  2. You run your code in another, or in an editor, where the environment is not active
  3. ModuleNotFoundError, despite the package being installed — just not in the Python that is running

Two habits prevent it:

Install with python -m pip rather than bare pip.

python -m pip install requests

That installs into the Python you just invoked, whatever pip alone might have resolved to. It removes an entire class of confusion.

Tell your editor which interpreter to use. In VS Code, the command palette, Python: Select Interpreter, and pick the one in .venv. The version appears in the bottom-right corner — the thing the setup lesson told you to check when something makes no sense.

Always exclude it from Git

# .gitignore
.venv/
__pycache__/
*.pyc

A virtual environment is large, platform-specific, and completely reproducible from requirements.txt. Committing one is a mistake — it bloats the repository and does not work on anyone else's machine anyway.

Commit the list of dependencies, never the dependencies themselves. That is the next lesson.

Conventions

Name it .venv. The leading dot hides it, most tools look for it automatically, and editors detect it without configuration. venv and env also appear in the wild.

One per project, inside the project folder. Not shared, not somewhere central.

Recreate rather than repair. If an environment gets into a confusing state, delete the folder and rebuild it. It takes a minute and costs nothing, because everything in it is reproducible:

rm -rf .venv
python -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt

That willingness to throw it away is itself the benefit.

Alternatives you will meet

The landscape has several tools, and they solve the same core problem:

  • venv — built in, no install, and what this course uses. Learn this first; everything else builds on the same idea.
  • uv — much faster, increasingly popular, handles environments and packages together.
  • Poetry — environments plus dependency resolution and publishing.
  • conda — common in data science, manages non-Python dependencies too.

Start with venv. It is always available, and understanding it makes the others obvious.

Practice

  1. Create a project folder and a .venv inside it.
  2. Activate it and confirm your prompt changes.
  3. Run python -c "import sys; print(sys.executable)" before and after activating. Compare.
  4. Run pip list inside a fresh environment. Note how little is there.
  5. Install requests inside the environment. Import it successfully. Then deactivate and try importing it again — read the ModuleNotFoundError and explain it in one sentence.
  6. Create two environments and install different versions of the same package in each. Confirm they do not interfere.
  7. Add .venv/ and __pycache__/ to a .gitignore and confirm git status stops mentioning them.
  8. Delete an environment and rebuild it from scratch. Time how long it takes.
  9. Point VS Code at your .venv interpreter and confirm the status bar shows it.

Next: installing packages properly, and making sure the versions you tested against are the versions that run.

Stuck on this lesson?

Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.

About the internship