venv#
Python includes (since version 3.3 released in 2012) the venv module to provide lightweight support for virtual environments, without the need for any third-party tools.
Usage#
When inside the folder of your Python project, the following command creates a new virtual environment
$ python -m venv .venv
where .venv
is the conventional name for the virtual environment and the prepended dot makes the associated folder hidden on Unix systems.
Additional options allow to control some aspects during venv creation. See python -m venv --help
for details. In particular you can grant your venv access to the system-wide packages. This can be useful on HPC clusters, where the number-crunching libraries have been optimized for the platform and should not simply be re-installed with default options inside the virtual environment.
$ python -m venv --system-site-packages .venv
Tip
When using a version control system like git
, always make sure to ignore the .venv
folder by adding it to your project’s .gitignore
file. The virtual environment can quickly grow to over 100MB and is platform-dependent. It must therefore be excluded from the git history.
Once created, the virtual environment needs to be activated.
$ source .venv/bin/activate
C:\> .\venv\Scripts\Activate.ps1
Afterwards the pip
and python
commands should refer to the binaries inside the virtual environment.
$ which pip
/path/to/your/project/.venv/bin/pip
In particular pip
will install packages locally into the virtual environment.
When done, you can either close your shell or deactivate
the virtual environment
$ deactivate
Behind the scenes#
Let’s take a closer look at what is happening behind the scenes when creating and activating a virtual environment.
Contents of .venv#
We use the tree
command to list the (first three levels of) contents of the .venv/
directory.
$ tree -L 3 .venv/
.venv/
├── bin/ # directory with binaries and executable scripts
│ ├── Activate.ps1 # scripts to activate venv for different shells
│ ├── activate
│ ├── activate.csh
│ ├── activate.fish
│ ├── pip* # local pip wrapper scripts
│ ├── pip3*
│ ├── pip3.11*
│ ├── python -> python3.11*
│ ├── python3 -> python3.11*
│ └── python3.11 -> /path/to/your/python3.11* # symlink to your Python interpreter
├── include/ # directory to contain C header files
├── lib/
│ └── python3.11/
│ └── site-packages/ # directory to contain local Python packages
└── pyvenv.cfg # config file
Activation of .venv#
Feel free to inspect the code of .venv/bin/activate
to see what exactly is happening when activating a virtual environment. We highlight the main points:
the
VIRTUAL_ENV
shell environment variable is defined with the absolute path to the.venv
directory. This variable can be used to check if one is running inside a virtual environment and display its name in the shell prompt.the
.venv/bin
folder is prepended to yourPATH
so that all executables inside take precedence. This ensures that running apip
command actually invokes thepip
from inside the virtual environment, without having to give the full path.venv/bin/pip
. Similarly for thepython
interpreter itself and any executables installed by the Python packages inside the virtual environment.
Note that, given the activation is merely changing your shell’s PATH
, you don’t really need to first activate a virtual environment. Alternatively you may call the interpreter or scripts directly using their full .venv/bin/
path.
Conversely, when calling deactivate
all changes are reverted by resetting the shell environment variables to their previous state.