Sitemap

Deep Dive into Python Virtual Environments

5 min readSep 22, 2026

--

First article ever! Let’s get it started.

Everyone who uses Python has used virtual environments at least once. We open our project folder, run the commands below depending on our OS, install our project dependencies, and start building.

# UNIX Based systems
python3 -m venv .venv && source .venv/bin/activate

# Windows
python -m venv .venv && .venv\Scripts\activate

But what actually happens behind the scenes when we run the activation script? What do the generated files and folders do, and what do they contain?
This article answers all that, but first we need to understand what a virtual environment is.

What are Virtual Environments?

Imagine we have 2 babies in a house, baby A and baby B, and they both share several toys. One of those toys is the Omnitrix, but there’s only space for one of them in the toy pile.

  • Baby A only likes the Omnitrix from the original Ben 10.
  • Baby B only likes the Omnitrix from Ben 10: Omniverse.

This means that when either baby wants to play, the mother has to keep replacing the Omnitrix in the pile beforehand to avoid any of the babies crying, but this is tedious and unsustainable. So, is there any other solution?

Yes! The mother can have two separate toy piles for the two babies so one baby playing doesn’t affect the other, and they can both enjoy their own Omnitrix.

Python virtual environments work the same way. They isolate project dependencies to avoid conflicts when projects need different versions of the same package. This ensures that several projects can run on the same machine without any errors.
In the case above:
- Baby A and Baby B: 2 different projects.
- Toy pile: The global Python Installation.
- Separate toy piles: The 2 separate virtual environments.
- Omnitrix: A package like Django, FastAPI, requests and so on
- Mother: You, the developer.

Unpacking the .venv Folder

I’ll focus mainly on UNIX-based systems, as the process in Windows is a lot more complex and I haven’t explored that route yet.

If we run python3 -m venv .venv on our system (Ubuntu in my case), we can see that it generates a couple of files and folders here, namely the bin, include, lib, and lib64 folders and a pvenv.cfg file.

Here is what each component does:

Press enter or click to view image in full size
Folder structure of the .venv file
  • bin — This folder contains the executables and scripts that your project needs. It also contains the CLI programs like fastapi, pytest, and alembic you use in your projects. For example, let’s say I activate the environment and install the FastAPI package, which also installs a terminal application.
Press enter or click to view image in full size
activating the virtual environment and installing fastapi

Let’s now see how the bin folder looks:

Press enter or click to view image in full size
bin folder after installing fastapi

As we can see, it added the fastapi executable to the bin folder after the installation.

You’ll notice the bin folder also contains:

  • Activation scripts: Shell scripts (activate, activate.csh, activate.fish) used to activate the environment depending on your current shell.
  • Package installers: Tools like pip, uv which we use to install dependencies.
  • Python interpreter: The Python binary used to run our programs.

For ourpython executable, there’s an arrow (->) pointing to our global Python installation. This is called a symbolic link (aka symlink), which is basically like a shortcut, and what this does is that whenever we run the python3, python or python3.14, we execute the Python that is installed globally on our system.

Get Kamal Baiyewu’s stories in your inbox

Join Medium for free to get updates from this writer.

But because the binary detects the adjacent pyvenv.cfg, it dynamically re-points its sys.prefix (base directory of lib/site-packages) and package search path (sys.path) to .venv .

  • include — Contains C header files that some packages in your project might need.
  • lib — This contains the folder python{VERSION}/site-packages where packages are located when installed via a package manager like pip, uv, or poetry. In my case, with Python 3.14, packages are installed to lib/python3.14/site-packages/xxx .
Press enter or click to view image in full size
Before Installing fastapi
Press enter or click to view image in full size
after installing fastapi
  • lib64 — A symlink to the lib folder. It’s created when the 64-bit version of Python is installed
  • pyvenv.cfg-The configuration file for our virtual environment. It contains the following:
  • home — The base directory of the Python interpreter that the virtual environment is using.
  • include-system-site-packages — A flag that indicates whether the globally installed packages should be used by the project instead of the ones located in the ENV_NAME/lib/python{VERSION}/site-packages. By default, it is set to false.
  • version — The version of Python being used.
  • executable — The location of the Python executable used.
  • command — The command used to create the environment.
Press enter or click to view image in full size
This is what the file contains when we use the built-in venv module.

The built-in site module uses the settings above to set up our virtual environment.

Activating the Virtual Environment

Now that we’ve broken down the contents of the .venv folder, let’s take a look at the magic that happens when we run the command source .venv/bin/activate in our shell. In order:

  1. The activate script first createsdeactivate , which undoes the actions listed below.
  2. It sets the VIRTUAL_ENV environment variable to point to the absolute path of the .venv folder.
  3. Adds VIRTUAL_ENV/bin to the beginning of the terminal’s PATH environment variable. By doing this, whenever we run python within our environment, it uses the Python located in the .venv folder.
Press enter or click to view image in full size
Before activating virtual environment
Press enter or click to view image in full size
After. The highlighted section is the path to our bin. The Python we’re using also points to the one in the .venv folder as indicated by the which command.

4. Our shell prompt is also tweaked to show that we are currently in a virtual environment.

Press enter or click to view image in full size
Before activation
Press enter or click to view image in full size
After activation (the directory where .venv folder resides is used as the name)

I’m committing to writing one technical breakdown per week to solidify what I learn and help others along the way.

Thanks for reading, and have a wonderful day.

--

--