Python Virtual Environments (venv)

Python Virtual Environments: A Primer

by Martin Breuss Updated Reading time estimate 1h 37m intermediate devops tools

Creating a Python virtual environment allows you to manage dependencies separately for different projects, preventing conflicts and maintaining cleaner setups. With Python’s venv module, you can create isolated environments that use different versions of libraries or Python itself. This tutorial guides you through creating, activating, and managing these environments efficiently.

By the end of this tutorial, you’ll understand that:

  • Python virtual environments provide lightweight and isolated Python development environments.
  • You can use Python’s venv module to manage dependencies independently for each project.
  • You create and set up a venv in Python using the command python -m venv path/to/venv/.
  • You refer to a virtual environment by the folder name that you used when creating the venv.
  • You activate a venv on Windows with venv\Scripts\activate, and on macOS and Linux with source venv/bin/activate.
  • You can enable a venv in VS Code by opening the Command Palette and choosing Python: Select Interpreter.

Working with virtual environments is a common and effective practice in Python development. Gaining a better understanding of how they work, why you need them, and what you can do with them will help you master your Python programming workflow.

Here’s the trap, in one demo: when two projects install their dependencies into a single shared environment, the second pip install silently overwrites the first—so client-old, which needs the older Django, breaks. Flip it to per-project virtual environments to watch both get exactly the version they need:

Interactive diagram — enable JavaScript to view.

Throughout the tutorial, you can select code examples for either Windows, Linux, or macOS. Pick your platform at the top right of the relevant code blocks to get the commands that you need, and feel free to switch between them if you want to learn how to work with virtual environments on other operating systems.

Take the Quiz: Test your knowledge with our interactive “Python Virtual Environments: A Primer” quiz. You’ll receive a score upon completion to help you track your learning progress:


Interactive Quiz

Python Virtual Environments: A Primer

In this quiz, you'll test your understanding of Python virtual environments. With this knowledge, you'll be able to avoid dependency conflicts and help other developers reproduce your development environment.

How Can You Work With a Python Virtual Environment?

If you just need to get a virtual environment up and running to continue working on your favorite project, then this section is for you.

This tutorial uses Python’s venv module to create virtual environments. This module is part of Python’s standard library, and it’s been the officially recommended way to create virtual environments since Python 3.5.

For basic usage, venv is an excellent choice because it already comes packaged with your Python installation. With that in mind, you’re ready to create your first virtual environment.

Create It

Any time you’re working on a Python project that uses external dependencies you’re installing with pip, it’s best to first create a virtual environment:

Language: Windows PowerShell
PS> py -m venv venv\

This command allows the Python launcher for Windows to select an appropriate version of Python to execute. It comes bundled with the official installation and is the most convenient way to execute Python on Windows.

You can bypass the launcher and run the Python executable directly using the python command, but if you haven’t configured the PATH and PATHEXT variables, then you might need to provide the full path:

Language: Windows PowerShell
PS> C:\Users\Name\AppData\Local\Programs\Python\Python312\python -m venv venv\

The system path shown above assumes that you installed Python 3.12 using the Windows installer provided by the Python downloads page. The path to the Python executable on your system might be different. Working with PowerShell, you can find the path using the where.exe python command.

Language: Shell
$ python3 -m venv venv/

Many Linux operating systems ship with a version of Python 3. If python3 doesn’t work, then you’ll have to first install Python and you may need to use the specific name of the executable version that you installed, for example, python3.12 for Python 3.12.x. If that’s the case for you, remember to replace mentions of python3 in the code blocks with your specific version number.

Language: Shell
$ python3 -m venv venv/

Older versions of macOS come with a system installation of Python 2.7.x that you should never use to run your scripts. If you’re working on macOS < 12.3 and invoke the Python interpreter with python instead of python3, then you might accidentally start up the outdated system Python interpreter.

If running python3 doesn’t work, then you’ll have to first install a modern version of Python.

This command creates a new virtual environment named venv using Python’s built-in venv module. The first venv that you use in the command specifies the module, and the second venv/ sets the name for your virtual environment. You could name it differently, but calling it venv is a good practice for consistency.

Activate It

Great! Your project now has its own virtual environment. Generally, before you start to use it, you’ll activate the environment by executing a script that comes with the installation:

Language: Windows PowerShell
PS> venv\Scripts\activate
(venv) PS>

If your attempt to run this command produces an error, then you’ll first have to loosen the execution policy.

Language: Shell
$ source venv/bin/activate
(venv) $

Before you run this command, make sure that you’re in the folder containing the virtual environment you just created. If you’ve named your virtual environment something other than venv, then you’ll have to use that name in the path instead of venv when you source the activation script.

Once you can see the name of your virtual environment in your command prompt—in this case (venv)—then you’ll know that your virtual environment is active. Now you’re all set and ready to install your external packages!

Install Packages Into It

After you’ve created and activated your virtual environment, you can install any external dependencies that you need for your project:

Language: Windows PowerShell
(venv) PS> python -m pip install <package-name>
Language: Shell
(venv) $ python -m pip install <package-name>

This command is the default command that you should use to install external Python packages with pip. Because you first created and activated the virtual environment, pip will install the packages in an isolated location.

You can now install your packages to your virtual environment. To get to this point, you created a virtual environment named venv and then activated it in your current shell session.

As long as you don’t close your terminal, every Python package that you install will end up in this isolated environment instead of your global Python site-packages. This means that you can now work on your Python project without worrying about dependency conflicts.

Deactivate It

Once you’re done working with this virtual environment, you can deactivate it:

Language: Windows PowerShell
(venv) PS> deactivate
PS>
Language: Shell
(venv) $ deactivate
$

After executing the deactivate command, your command prompt returns to normal. This change means that you’ve exited your virtual environment. If you interact with Python or pip now, you’ll interact with your globally configured Python environment.

If you want to go back into a virtual environment that you’ve created before, then you’ll need to run the activate script for that virtual environment once again.

Before you install a package, look for the name of your virtual environment within parentheses just before your command prompt. In the example above, the name of the environment is venv.

If the name appears, then you know that your virtual environment is active and you can install your external dependencies. If you don’t see the name in your command prompt, remember to activate your Python virtual environment before installing any packages.

At this point, you’ve covered the essentials of working with Python virtual environments using the venv module.

How Do You Enable a Venv in Your IDE?

Working with virtual environments directly from your Integrated Development Environment (IDE) can streamline your development process. Popular IDEs like Visual Studio Code (VS Code) and PyCharm provide built-in support for managing Python virtual environments, allowing you to create, activate, and manage them without leaving the editor.

Create and Activate a Virtual Environment in VS Code

Visual Studio Code is a lightweight but powerful code editor that supports Python development. To create and activate a Python environment in VS Code, follow these steps:

  1. Open Your Workspace: Launch VS Code and open the folder that contains your Python project.

  2. Open the Integrated Terminal: Navigate to View → Terminal in the menu to launch the integrated terminal.

  3. Create a Virtual Environment: In the terminal, create a new virtual environment with the venv module using the commands that you saw earlier.

  4. Activate the Virtual Environment: Still using the integrated terminal, use your platform-specific command to activate the virtual environment.

VS Code may automatically detect the active virtual environment. To ensure that you’re using it for all project files, open the Command Palette by pressing Ctrl+Shift+P on Windows and Linux, or Cmd+Shift+P on macOS, and start typing Python: Select Interpreter until it shows up as an option:

A view of the VS Code editor with an open command prompt showing the option to select the Python interpreter is highlighted

After you press Enter to select that command option, VS Code will display a drop-down of available Python interpreters. This list may be shorter or longer for you, depending on how many virtual environments VS Code discovers on your system. Use the arrow keys to find the virtual environment you just created:

A view on the VS Code command palette displaying a drop down to select a Python interpreter from multiple options

You’ll know that it’s the right one if the path to the interpreter displays as .\venv\Scripts\python on Windows or ./venv/bin/python on macOS and Linux. Press Enter to select that interpreter within your newly created virtual environment.

With these steps, you’ve successfully set up and activated a virtual environment in VS Code. You’ll also see the changes reflected in the VS Code status bar, which shows the name of the active interpreter.

Create and Activate a Virtual Environment in PyCharm

PyCharm, another leading Python IDE, offers robust support for managing virtual environments within your Python projects. In a couple of scenarios, PyCharm handles the virtual environment creation and activation for you.

If you open an existing PyCharm project that already has a virtual environment in the project folder, then PyCharm will automatically recognize and activate it for you:

PyCharm interface showing an activated virtual environment after opening a project that already has a virtual environment

If you create a new PyCharm project, then it’ll prompt you to create a virtual environment by selecting a tooling option and a base Python interpreter:

PyCharm window prompting you to create a new virtual environment for a new project

After you click Create, PyCharm sets up the virtual environment with the default name .venv and activates it for you:

PyCharm project windows showing a new and activated virtual environment path

Both of these options are straightforward and you won’t have to do a lot for PyCharm to present you with a working virtual environment.

Finally, if you open up an existing project that doesn’t yet have a virtual environment folder, then you can still configure the Python interpreter in PyCharm.

To start, open your project in PyCharm using File → Open… and select your existing project folder.

Next, open your project settings by navigating to File → Settings on Windows—or PyCharm → Settings on macOS—and from the left sidebar, select Project: Your Project Name → Python Interpreter:

Project settings of a PyCharm project with the Python Interpreter setting selected in the side bar

Click on Add Interpreter → Add Local Interpreter to open a pop-up window that allows you to create a new virtual environment. You can customize what tool and Python base interpreter you want to use, but in most cases, you can just leave the default settings and click OK:

Pop up window in PyCharm giving you the option to create a new Python interpreter

PyCharm creates and activates a new virtual environment in your project folder that it calls .venv by default. Click OK again to exit your project settings. You can confirm that your project is set up to use your new virtual environment called .venv by hovering over the name of the Python interpreter in the bottom right corner:

PyCharm main project window showing an activated virtual environment path when hovering over the Python interpreter name in the bottom right corner

It’ll show the path to your Python interpreter that’s nested within the virtual environment folder. Any scripts that you run through PyCharm will use the configured virtual environment without you needing to manually activate it.

Now you know how to create and activate virtual environments manually, and how to set them up in two popular Python IDEs. If that’s all you need, then happy trails as you continue creating!

However, if you want to learn the nuts and bolts of what exactly happens when you create a virtual environment using venv, why so many tutorials ask you to make one in the first place, and what a virtual environment really is, then keep on reading! You’re about to go deep!

Why Do You Need Virtual Environments?

Nearly everyone in the Python community suggests that you use virtual environments for all your projects. But why? If you want to find out why you need to set up a virtual environment in the first place, then this is the right section for you.

The short answer is that Python isn’t great at dependency management. If you’re not specific, then pip will place all the external packages that you install in a folder called site-packages/ in your base Python installation.

Technically, Python comes with two site-packages folders:

  1. purelib/ should contain only modules written in pure Python code.
  2. platlib/ should contain binaries that aren’t written in pure Python, for example .dll, .so, or .pydist files.

You can find these folders in different locations if you’re working on Fedora or RedHat Linux distributions.

However, most operating systems implement Python’s site-packages setting so that both locations point to the same path, effectively creating a single site-packages folder. You can check the paths using sysconfig:

Language: Python
>>> import sysconfig
>>> sysconfig.get_path("purelib")
'C:\\Users\\Name\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages'
>>> sysconfig.get_path("platlib")
'C:\\Users\\Name\\AppData\\Local\\Programs\\Python\\Python312\\Lib\\site-packages'
Language: Python
>>> import sysconfig
>>> sysconfig.get_path("purelib")
'/usr/local/lib/python3.12/site-packages'
>>> sysconfig.get_path("platlib")
'/usr/local/lib/python3.12/site-packages'
Language: Python
>>> import sysconfig
>>> sysconfig.get_path("purelib")
'/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages'
>>> sysconfig.get_path("platlib")
'/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages'

Most likely, both outputs will show you the same path. If both outputs are the same, then your operating system doesn’t put purelib modules into a different folder than platlib modules. If two different paths show up, then your operating system makes this distinction.

Even if your operating system distinguishes between the two, dependency conflicts will still arise because all purelib modules will go into a single location for purelib modules, and the same will happen with the platlib modules.

To work with virtual environments, you don’t need to worry about the implementation details of a single site-packages folder or two separate ones. In fact, you probably won’t ever need to think about it again. You can, however, keep in mind that when someone mentions Python’s site-packages directory, they could be talking about two different directories.

Several issues can come up if all of your external packages land in the same folder. Next up, you’ll learn more about these issues and other problems that virtual environments mitigate.

Avoid System Pollution

Linux and macOS come preinstalled with a version of Python that the operating system uses for internal tasks.

If you install packages to your operating system’s global Python, these packages will mix with the system-relevant packages. This mix-up could have unexpected side effects on tasks crucial to your operating system’s normal behavior.

Additionally, if you update your operating system, then the packages you installed might get overwritten and lost, and you don’t want either of those headaches to happen!

Sidestep Dependency Conflicts

One of your projects might require a different version of an external library compared to another project. If you only have one place to install packages, then you won’t be able to work with two different versions of the same library. This is a common reason why it’s recommended to use a Python virtual environment.

To better understand why this is so important, imagine you’re building Django websites for two different clients:

  • One client is comfortable with their existing web app, which you initially built using Django 2.2.26, and this client refuses to update their project to a modern Django version.
  • Another client wants you to include async functionality in their website, which is only available starting with Django 3.1. You’ll want to use a modern Django version for this client!

If you install Django globally, you can only have one version installed:

Language: Windows PowerShell
PS> py -m pip install django==2.2.26
PS> py -m pip list
Package  Version
-------- -------
Django   2.2.26
pip      24.2
pytz     2024.1
sqlparse 0.5.1

PS> py -m pip install django==5.1
PS> py -m pip list
Package  Version
-------- -------
asgiref  3.8.1
Django   5.1
pip      24.2
pytz     2024.1
sqlparse 0.5.1
tzdata   2024.1
Language: Shell
$ python3 -m pip install django==2.2.26
$ python3 -m pip list
Package  Version
-------- -------
Django   2.2.26
pip      24.2
pytz     2024.1
sqlparse 0.5.1

$ python3 -m pip install django==5.1
$ python3 -m pip list
Package  Version
-------- -------
asgiref  3.8.1
Django   5.1
pip      24.2
pytz     2024.1
sqlparse 0.5.1

If you install two different versions of the same package into your global Python environment, the second installation overwrites the first one. For the same reason, having a single virtual environment for both clients won’t work either. You can’t have two different versions of the same package in a single Python environment.

Looks like you won’t be able to work on one of the two projects with this setup! However, if you create a virtual environment for each of your clients’ projects, then you can install a different version of Django into each of them:

Language: Windows PowerShell
PS> py -m venv client-old\
PS> client-old\Scripts\activate
(client-old) PS> python -m pip install django==2.2.26
(client-old) PS> python -m pip list
Package  Version
-------- -------
Django   2.2.26
pip      24.2
pytz     2024.1
sqlparse 0.5.1
(client-old) PS> deactivate

PS> py -m venv client-new\
PS> client-new\Scripts\activate
(client-new) PS> python -m pip install django==5.1
(client-new) PS> python -m pip list
Package  Version
-------- -------
asgiref  3.8.1
Django   5.1
pip      24.2
sqlparse 0.5.1
tzdata   2024.1
(client-new) PS> deactivate
Language: Shell
$ python3 -m venv client-old/
$ source client-old/bin/activate
(client-old) $ python -m pip install django==2.2.26
(client-old) $ python -m pip list
Package  Version
-------- -------
Django   2.2.26
pip      24.2
pytz     2024.1
sqlparse 0.5.1
(client-old) $ deactivate

$ python3 -m venv client-new/
$ source client-new/bin/activate
(client-new) $ python -m pip install django==5.1
(client-new) $ python -m pip list
Package  Version
-------- -------
asgiref  3.8.1
Django   5.1
pip      24.2
sqlparse 0.5.1
(client-new) $ deactivate

If you now activate either of the two virtual environments, then you’ll notice that it still holds its own specific version of Django. The two environments also have different dependencies, and each only contains the dependencies necessary for that version of Django.

With this setup, you can activate one environment when you work on one project and another when you work the other project. Now you can keep any number of clients happy at the same time!

Minimize Reproducibility Issues

If all your packages live in one location, then it’ll be difficult to only pin dependencies that are relevant for a single project.

If you’ve worked with Python for a while, then your global Python environment might already include all sorts of third-party packages. If that’s not the case, then pat yourself on the back! You’ve probably installed a new version of Python recently, or you already know how to handle virtual environments to avoid system pollution.

To clarify what reproducibility issues you can encounter when sharing a Python environment across multiple projects, you’ll look at an example next. Imagine you’ve worked on two independent projects over the past month:

  1. A web scraping project with Beautiful Soup
  2. A Flask application

Unaware of virtual environments, you installed all necessary packages into your global Python environment:

Language: Windows PowerShell
PS> py -m pip install beautifulsoup4 requests
PS> py -m pip install flask
Language: Shell
$ python3 -m pip install beautifulsoup4 requests
$ python3 -m pip install flask

Your Flask app has turned out to be quite helpful, so other developers want to work on it as well. They need to reproduce the environment that you used for working on it. You want to go ahead and pin your dependencies so that you can share your project online:

Language: Windows PowerShell
PS> py -m pip freeze
beautifulsoup4==4.12.3
blinker==1.8.2
certifi==2024.8.30
charset-normalizer==3.3.2
click==8.1.7
colorama==0.4.6
Flask==3.0.3
idna==3.8
itsdangerous==2.2.0
Jinja2==3.1.4
MarkupSafe==2.1.5
requests==2.32.3
soupsieve==2.6
urllib3==2.2.2
Werkzeug==3.0.4
Language: Shell
$ python3 -m pip freeze
beautifulsoup4==4.12.3
blinker==1.8.2
certifi==2024.8.30
charset-normalizer==3.3.2
click==8.1.7
Flask==3.0.3
idna==3.8
itsdangerous==2.2.0
Jinja2==3.1.4
MarkupSafe==2.1.5
requests==2.32.3
soupsieve==2.6
urllib3==2.2.2
Werkzeug==3.0.4

Which of these packages are relevant to your Flask app, and which ones are here because of your web scraping project? It’s hard to tell when all external dependencies are in a single bucket.

With a single environment like this, you’d have to manually go through the dependencies and know which are necessary for your project and which aren’t. At best, this approach is tedious, but even more so, it’s error-prone.

If you use a separate virtual environment for each of your projects, then it’ll be more straightforward to read the project requirements from your pinned dependencies. That means you can more easily share your success when you develop a great app, making it possible for others to collaborate with you!

Dodge Installation Privilege Lockouts

Finally, you may need administrator privileges on a computer to install packages into the host Python’s site-packages directory. In a corporate work environment, you most likely won’t have that level of access to the machine that you’re working on.

If you use virtual environments, then you create a new installation location within the scope of your user privileges, which allows you to install and work with external packages.

Whether you’re coding as a hobby on your own machine, developing websites for clients, or working in a corporate environment, using a virtual environment will save you lots of grief in the long run.

What Is a Python Virtual Environment?

At this point, you’re convinced that you want to work with virtual environments. Great, but what are you working with when you use a virtual environment? If you want to understand what virtual environments are, then this is the right section for you.

The short answer is that a Python virtual environment is a folder structure that gives you everything you need to run a lightweight yet isolated Python environment.

A Folder Structure

When you create a new virtual environment using the venv module, Python creates a self-contained folder structure and copies or symlinks the Python executable files into that folder structure.

You don’t need to dig deeply into this folder structure to learn more about what virtual environments are made of. In just a bit, you’ll carefully scrape off the topsoil and investigate the high-level structures that you uncover.

However, if you already have your shovel ready and you’re itching to dig, then open the collapsible section below:

Welcome, brave one. You’ve accepted the challenge to venture deeper into your virtual environment’s folder structure! In this collapsible section, you’ll find instructions on how to take a look into that dark abyss.

On your command line, navigate to the folder that contains your virtual environment. Take a deep breath and brace yourself, then execute the tree command to display the contents of the directory:

Language: Windows PowerShell
PS> tree venv\ /F
Language: Shell
$  tree venv/

You may need to first install tree, for example with sudo apt install tree.

Language: Shell
$ tree venv/

You may need to first install tree, for example by using HomeBrew.

The tree command displays the content of your venv directory in a very long tree structure.

However you end up displaying the contents of the venv/ folder, you might be surprised by what you find. Many developers experience a slight shock when they first take a peek. There are a lot of files in there!

If this was your first time and you felt that way, then welcome to the group of people who have taken a look and been a bit overwhelmed !

A virtual environment folder contains a lot of files and folders, but you might notice that most of what makes this tree structure so long rests inside the site-packages/ folder. If you trim down the subfolders and files in there, you end up with a tree structure that isn’t too overwhelming:

venv\
│
├── Include\
│
├── Lib\
│   │
│   └── site-packages\
│       │
│       ├── pip\
│       │
│       └── pip-24.2.dist-info\
│
│
├── Scripts\
│   ├── Activate.ps1
│   ├── activate
│   ├── activate.bat
│   ├── deactivate.bat
│   ├── pip.exe
│   ├── pip3.12.exe
│   ├── pip3.exe
│   ├── python.exe
│   └── pythonw.exe
│
└── pyvenv.cfg
venv/
│
├── bin/
│   ├── Activate.ps1
│   ├── activate
│   ├── activate.csh
│   ├── activate.fi