How Virtualenv Works: Behind the Scenes

Posted by Afsal on 14-Feb-2025

Hi Pythonistas!

Python’s virtualenv (or venv in modern Python versions) is a powerful tool that allows you to create isolated environments for your projects. But how does it actually work? Let’s dive into the internals of virtualenv and understand what happens when you create and activate a virtual environment. If you are not familiar with virtualenv we have post on the basics

What is Virtualenv?
virtualenv is a tool that creates an isolated Python environment where you can install packages without affecting the system-wide Python installation. This helps in:

  • Avoiding package version conflicts across projects.
  • Preventing accidental modifications to system Python.
  • Creating reproducible environments for deployment.

How Virtualenv is Created
When you create a virtual environment with:

python -m venv myenv

or using virtualenv

virtualenv myenv

it performs several key actions:

Creates a Directory Structure

A new folder (myenv/) is created, which contains:

myenv/
│── bin/ (or Scripts/ on Windows)
│   ├── python (or python.exe)
│   ├── pip
│   ├── activate
│── lib/ (or Lib/ on Windows)
│   ├── site-packages/
│── pyvenv.cfg

Let’s break it down:

bin/ (or Scripts/ on Windows) → Contains Python executables (python, pip, etc.).
lib/site-packages/ → Stores installed packages for this virtual environment.
pyvenv.cfg → A configuration file storing details about the environment, including the Python version used.
Copies the Python Executable

The python executable inside the virtual environment is not a full copy of Python but a symlink (on Unix) or a lightweight wrapper (on Windows). It ensures that Python runs within this isolated environment.

Sets Up site-packages

Normally, Python’s global packages are stored in /usr/lib/pythonX.X/site-packages. Virtualenv redirects package installation to the lib/site-packages/ folder inside myenv/, so dependencies remain project-specific.

What Happens During Activation?
When you run:

source myenv/bin/activate  # macOS/Linux

myenv\Scripts\Activate  # Windows PowerShell

the activation script does the following:

Modifies $PATH: Prepends myenv/bin/ (or myenv\Scripts\) to PATH, ensuring that python and pip point to the virtual environment’s versions.
Sets $VIRTUAL_ENV: Adds an environment variable to store the virtual environment’s location.
Changes the shell prompt: Displays (myenv) in the terminal as a reminder.

afsal@afsal:~/Desktop/experiments$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin
afsal@afsal:~/Desktop/experiments$ echo $VIRTUAL_ENV

afsal@afsal:~/Desktop/experiments$ source myvenv/bin/activate
(myvenv) afsal@afsal:~/Desktop/experiments$ echo $PATH
/home/afsal/Desktop/experiments/myvenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin
(myvenv) afsal@afsal:~/Desktop/experiments$ echo $VIRTUAL_ENV
/home/afsal/Desktop/experiments/myvenv
(myvenv) afsal@afsal:~/Desktop/experiments$ 

What Happens on Deactivation?
Running:

deactivate

Restores the original PATH.
Removes $VIRTUAL_ENV.
Resets the shell prompt.

(myvenv) afsal@afsal:~/Desktop/experiments$ deactivate
afsal@afsal:~/Desktop/experiments$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin
afsal@afsal:~/Desktop/experiments$ echo $VIRTUAL_ENV

afsal@afsal:~/Desktop/experiments$ 

How Does Virtualenv Isolate Dependencies?

Any package installed via pip install inside the virtual environment goes into lib/site-packages/ instead of the global Python installation. Running python inside the virtual environment ensures that it only has access to the packages installed in the environment, avoiding conflicts with system-wide libraries.
To confirm, run:

afsal@afsal:~/Desktop/experiments$ which python3
/usr/bin/python3
afsal@afsal:~/Desktop/experiments$ source myvenv/bin/activate
(myvenv) afsal@afsal:~/Desktop/experiments$ which python3
/home/afsal/Desktop/experiments/myvenv/bin/python3
(myvenv) afsal@afsal:~/Desktop/experiments$ 

How Virtualenv Differs from System Python

Feature System Python Virtual Environment
Package Scope Global Project-specific
Dependencies Shared Isolated
Risk of Conflict High Low
Requires Admin Privileges Yes No

How to Delete a Virtual Environment

Since virtualenv is just a directory, deleting it is as simple as running:

rm -rf myenv  # macOS/Linux

rmdir /s /q myenv  # Windows

Virtualenv (or venv) works by creating an isolated directory, setting up a local Python binary, and modifying environment variables to ensure packages remain project-specific. This makes it an essential tool for Python development!