Python Virtual Environments: Complete Guide to venv, pipenv, and Poetry

February 12, 2026 · 22 min read

Every Python developer eventually encounters the same painful scenario: you install a package for one project and it breaks another. Project A needs Django 4.2 while Project B requires Django 5.0. A system-wide pip install overwrites the version you need elsewhere. Your colleague clones your repo and nothing works because they have different package versions. Virtual environments solve all of these problems by giving each project its own isolated Python installation with its own set of packages.

This guide covers every major tool for managing Python virtual environments in 2026. We start with the built-in venv module and pip, then move through pipenv, Poetry, conda, virtualenvwrapper, and pyenv. Each section includes real commands you can run immediately, along with the reasoning for when to choose each tool.

⚙ Related tools: Generate shell commands with our Bash Commands Cheat Sheet, reference Python syntax with the Python Cheat Sheet, and format configuration files with the JSON Formatter.

Table of Contents

  1. What Are Virtual Environments and Why They Matter
  2. venv: The Built-In Solution
  3. pip and requirements.txt
  4. pipenv: Pip and Virtualenv Combined
  5. Poetry: Modern Dependency Management
  6. Conda Environments
  7. virtualenvwrapper
  8. Working with Multiple Python Versions (pyenv)
  9. Comparison: venv vs virtualenv vs pipenv vs Poetry vs conda
  10. Best Practices for Project Structure
  11. Troubleshooting Common Issues
  12. Frequently Asked Questions

1. What Are Virtual Environments and Why They Matter

A Python virtual environment is a self-contained directory tree that contains a Python installation for a particular version of Python, plus additional packages. When you activate a virtual environment, the python and pip commands point to that environment's copies instead of the system-wide installation. Any package you install goes into the environment's site-packages directory, not the global one.

Without virtual environments, you face several real problems:

The concept is simple: each project gets its own Python and its own packages. The implementation details vary between tools, but this core idea remains the same across venv, virtualenv, pipenv, Poetry, and conda.

2. venv: The Built-In Solution

The venv module is included in Python 3.3 and later. It is the officially recommended way to create virtual environments and requires no additional installation.

Creating a Virtual Environment

# Create a virtual environment in the current directory
python3 -m venv .venv

# Or with a different name
python3 -m venv myproject-env

# Create with access to system site-packages
python3 -m venv .venv --system-site-packages

# Create with a specific prompt name (shown in terminal)
python3 -m venv .venv --prompt myproject

The .venv naming convention is widely adopted because it is hidden by default on Unix systems, immediately recognizable, and most IDEs detect it automatically.

Activating and Deactivating

# Linux / macOS (bash/zsh)
source .venv/bin/activate

# Linux / macOS (fish shell)
source .venv/bin/activate.fish

# Windows (Command Prompt)
.venv\Scripts\activate.bat

# Windows (PowerShell)
.venv\Scripts\Activate.ps1

# After activation, your prompt changes:
# (.venv) user@host:~/myproject$

# Verify which Python is active
which python    # /home/user/myproject/.venv/bin/python

# Deactivate when done
deactivate

When a virtual environment is active, the python and pip commands automatically point to the environment's binaries. You do not need to use python3 or pip3.

What Is Inside a Virtual Environment

.venv/
    bin/           # activate scripts, python/pip symlinks
    include/       # C header files for compiling extensions
    lib/python3.12/
        site-packages/  # all installed packages go here
    pyvenv.cfg     # config: home path, Python version, site-packages flag

The virtual environment is just a directory. You can delete it with rm -rf .venv and recreate it at any time. Environments are disposable and cheap to rebuild.

3. pip and requirements.txt

Once you have a virtual environment active, pip is how you install packages. The requirements.txt file records which packages your project depends on so others can reproduce the environment.

Installing Packages

# Install a single package (latest version)
pip install requests

# Install a specific version
pip install requests==2.31.0

# Install with version constraints
pip install "requests>=2.28,<3.0"
pip install "django~=4.2.0"    # compatible release (4.2.x)

# Install from a requirements file
pip install -r requirements.txt

# Upgrade a package
pip install --upgrade requests

# Install in editable mode (for development)
pip install -e .
pip install -e ".[dev,test]"   # with optional extras

Managing requirements.txt

# Generate requirements from current environment
pip freeze > requirements.txt

# Output looks like:
# certifi==2024.2.2
# charset-normalizer==3.3.2
# requests==2.31.0
# urllib3==2.2.1

# Install from requirements file
pip install -r requirements.txt

# Show installed packages / check outdated
pip list
pip list --outdated

# Uninstall a package
pip uninstall requests

Separate Requirements Files

# requirements.txt (production)
flask==3.0.2
sqlalchemy==2.0.28
gunicorn==21.2.0

# requirements-dev.txt (development)
-r requirements.txt
pytest==8.0.2
black==24.2.0
ruff==0.3.0
mypy==1.8.0

# Install for development
pip install -r requirements-dev.txt

pip-tools: Better Requirements Management

# Install pip-tools
pip install pip-tools

# Create requirements.in with direct dependencies only
# requirements.in: flask, sqlalchemy, gunicorn

# Compile pinned requirements with all transitive dependencies
pip-compile requirements.in

# Sync your environment to match requirements.txt exactly
pip-sync requirements.txt

# Upgrade a specific package
pip-compile --upgrade-package flask requirements.in

pip-tools bridges the gap between manual pip freeze and full-featured tools like Poetry. You maintain direct dependencies in .in files, and pip-compile resolves and pins all transitive dependencies automatically.

4. pipenv: Pip and Virtualenv Combined

Pipenv combines pip and virtualenv into a single workflow. It automatically creates and manages virtual environments, uses a Pipfile instead of requirements.txt, and generates a Pipfile.lock for deterministic builds.

# Install pipenv
pip install pipenv

# Create a new project with a virtual environment
mkdir myproject && cd myproject
pipenv install

# Install packages (creates Pipfile and Pipfile.lock)
pipenv install requests flask

# Install development dependencies
pipenv install --dev pytest black ruff

# Activate the virtual environment shell
pipenv shell

# Run a command without activating
pipenv run python app.py
pipenv run pytest

# Exit the pipenv shell
exit

The Pipfile

[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
requests = "*"
flask = ">=3.0"

[dev-packages]
pytest = "*"
black = "*"

[requires]
python_version = "3.12"

Common pipenv Commands

pipenv install              # install from Pipfile
pipenv install --dev        # include dev dependencies
pipenv update               # update all packages
pipenv graph                # show dependency graph
pipenv check                # check for vulnerabilities
pipenv requirements > requirements.txt  # export
pipenv uninstall requests   # remove a package
pipenv --rm                 # remove the virtual environment
pipenv --venv               # show venv location
pipenv --py                 # show Python path

Pipenv works well for application development with a straightforward workflow and lock file for reproducibility. However, it does not support building and publishing Python packages, and its dependency resolution can be slow for large projects.

5. Poetry: Modern Dependency Management

Poetry is the most feature-complete dependency management tool in the Python ecosystem as of 2026. It handles virtual environments, dependency resolution, lock files, package building, and publishing to PyPI — all from a single pyproject.toml file.

Installing and Configuring Poetry

# Official installer (recommended)
curl -sSL https://install.python-poetry.org | python3 -

# Or with pipx
pipx install poetry

# Configure Poetry to create venvs inside the project directory
poetry config virtualenvs.in-project true

Creating and Managing Projects

# Create a new project from scratch
poetry new myproject

# Or initialize in an existing project
cd existing-project
poetry init

# Add dependencies
poetry add requests flask sqlalchemy

# Add development dependencies
poetry add --group dev pytest black ruff mypy

# Add with version constraints
poetry add "django>=4.2,<5.0"

# Install all dependencies (creates poetry.lock)
poetry install

# Install without dev dependencies (production)
poetry install --without dev

# Update dependencies
poetry update
poetry remove flask

The pyproject.toml File

[tool.poetry]
name = "myproject"
version = "0.1.0"
description = "A sample Python project"
authors = ["Your Name <your@email.com>"]

[tool.poetry.dependencies]
python = "^3.10"
requests = "^2.31"
flask = "^3.0"

[tool.poetry.group.dev.dependencies]
pytest = "^8.0"
black = "^24.2"

[tool.poetry.scripts]
myapp = "myproject.cli:main"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Running Commands

poetry run python app.py         # run in venv
poetry run pytest                # run tests
poetry shell                     # activate shell
poetry env info                  # show env details
poetry show --tree               # dependency tree
poetry export -f requirements.txt --output requirements.txt
poetry build                     # create .whl and .tar.gz
poetry publish                   # publish to PyPI

Poetry's advantages over pipenv: faster dependency resolution, package building and publishing, dependency groups, a single pyproject.toml following PEP 621, and more active development. For new projects in 2026, Poetry is the recommended choice.

6. Conda Environments

Conda is a cross-platform package and environment manager from Anaconda or Miniconda. Unlike venv and pip, conda can manage non-Python dependencies (C libraries, R packages, system tools) and install different Python versions per environment. It is the standard tool in data science.

# Install Miniconda (minimal installer)
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
bash Miniconda3-latest-Linux-x86_64.sh

# Create an environment with a specific Python version
conda create --name myproject python=3.12

# Activate / deactivate
conda activate myproject
conda deactivate

# Install packages
conda install numpy pandas scikit-learn matplotlib
conda install -c conda-forge jupyterlab

# List environments
conda env list

# Export / recreate environment
conda env export > environment.yml
conda env create -f environment.yml

# Export only explicitly installed packages (cleaner)
conda env export --from-history > environment.yml

# Remove an environment
conda env remove --name myproject

The environment.yml File

name: myproject
channels:
  - conda-forge
  - defaults
dependencies:
  - python=3.12
  - numpy=1.26
  - pandas=2.2
  - scikit-learn=1.4
  - pip:
    - flask==3.0.2
    - custom-package==1.0.0

The pip: section allows pip-only packages not available in conda channels. Always install conda packages first, then pip packages. Conda is the right choice for data science, ML, or scientific computing with complex C/Fortran dependencies. For web development, venv with pip or Poetry is simpler.

7. virtualenvwrapper

Virtualenvwrapper provides convenience shell commands for managing virtual environments, storing all environments in a central location rather than inside each project directory.

# Install and configure
pip install virtualenvwrapper

# Add to ~/.bashrc or ~/.zshrc:
export WORKON_HOME=$HOME/.virtualenvs
export PROJECT_HOME=$HOME/projects
export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
source /usr/local/bin/virtualenvwrapper.sh

# Core commands
mkvirtualenv myproject              # create environment
mkvirtualenv myproject --python=python3.11  # specific version
workon                              # list environments
workon myproject                    # activate
deactivate                          # deactivate
rmvirtualenv myproject              # remove
mkproject myproject                 # create project + env
cdproject                           # cd to project dir
cpvirtualenv myproject myproject-copy  # clone

Virtualenvwrapper shines when you work on many projects and want quick switching with workon projectname. However, Poetry and pipenv handle environment management automatically, making virtualenvwrapper less necessary for modern workflows.

8. Working with Multiple Python Versions (pyenv)

Pyenv lets you install and switch between multiple Python versions on the same machine. It intercepts Python commands using shim executables and redirects them to the correct version based on your configuration.

Installing pyenv

# Install on Linux/macOS
curl https://pyenv.run | bash

# Add to ~/.bashrc or ~/.zshrc:
export PYENV_ROOT="$HOME/.pyenv"
[[ -d $PYENV_ROOT/bin ]] && export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"

# On macOS with Homebrew
brew install pyenv

# Install build dependencies (Ubuntu/Debian)
sudo apt install -y build-essential libssl-dev zlib1g-dev \
    libbz2-dev libreadline-dev libsqlite3-dev curl git \
    libncursesw5-dev xz-utils tk-dev libxml2-dev \
    libxmlsec1-dev libffi-dev liblzma-dev

Managing Python Versions

# List available / install specific versions
pyenv install --list | grep "^  3\."
pyenv install 3.12.1
pyenv install 3.11.7

# Set global default / project-local / shell-session version
pyenv global 3.12.1
pyenv local 3.11.7      # creates .python-version file
pyenv shell 3.10.13

# List installed versions / check active version
pyenv versions
pyenv version

pyenv + venv Workflow

# Set the Python version for your project
cd ~/projects/myproject
pyenv local 3.12.1

# Create a virtual environment using that version
python -m venv .venv
source .venv/bin/activate

# Now you have an isolated environment running Python 3.12.1
pip install flask requests

pyenv-virtualenv Plugin

# Install the plugin
git clone https://github.com/pyenv/pyenv-virtualenv.git \
    $(pyenv root)/plugins/pyenv-virtualenv
eval "$(pyenv virtualenv-init -)"

# Create a virtual environment tied to a Python version
pyenv virtualenv 3.12.1 myproject-env

# Activate or set as local environment
pyenv activate myproject-env
pyenv local myproject-env    # auto-activates on cd

# List / deactivate / delete
pyenv virtualenvs
pyenv deactivate
pyenv virtualenv-delete myproject-env

The pyenv local command is powerful: when you cd into a directory with a .python-version file, pyenv automatically switches to the correct Python version. No manual activation needed.

9. Comparison: venv vs virtualenv vs pipenv vs Poetry vs conda

Feature venv virtualenv pipenv Poetry conda
Built into PythonYes (3.3+)NoNoNoNo
Lock fileNo (use pip-tools)NoPipfile.lockpoetry.lockNo (conda-lock)
Dependency resolutionBasicBasicGoodExcellentExcellent
Manage Python versionsNoNoNoNoYes
Non-Python packagesNoNoNoNoYes
Build and publishNoNoNoYesYes
Config fileNoneNonePipfilepyproject.tomlenvironment.yml
Speed (env creation)FastVery fastModerateFastSlow
Best forSimple projectsPython 2ApplicationsLibraries + appsData science

Decision Guide

10. Best Practices for Project Structure

Recommended Project Layout

myproject/
    .venv/                  # virtual environment (NOT in git)
    .python-version         # pyenv version file (optional)
    .gitignore
    pyproject.toml          # project metadata and dependencies
    README.md
    src/
        myproject/
            __init__.py
            main.py
            models.py
    tests/
        test_main.py
        conftest.py
    scripts/
        seed_db.py

.gitignore for Virtual Environments

# Virtual environments
.venv/
venv/
env/

# Python
__pycache__/
*.py[cod]
*.egg-info/
dist/
build/

# IDE
.vscode/
.idea/

Key Best Practices

11. Troubleshooting Common Issues

ModuleNotFoundError After Installing a Package

# Check which Python/pip you are actually running
which python    # should point to .venv/bin/python
which pip       # should point to .venv/bin/pip

# If they point to /usr/bin/python, your venv is not activated
source .venv/bin/activate

# Verify the package is installed
pip list | grep package-name

# IDE: make sure it uses the venv Python
# VS Code: Ctrl+Shift+P > Python: Select Interpreter
# PyCharm: Settings > Project > Python Interpreter

Permission Denied Errors

# NEVER use sudo with pip in a virtual environment
# Wrong:
sudo pip install requests

# Right: activate the venv first
source .venv/bin/activate
pip install requests

# If the venv has permission issues, recreate it
rm -rf .venv && python3 -m venv .venv && source .venv/bin/activate

PowerShell Execution Policy (Windows)

# If you see "running scripts is disabled on this system":
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
.venv\Scripts\Activate.ps1

Python Version Mismatch

# The venv is tied to the Python version that created it
# If you upgrade Python and the old version is removed, the venv breaks
cat .venv/pyvenv.cfg | grep version

# Recreate if the version does not match:
rm -rf .venv && python3 -m venv .venv
source .venv/bin/activate && pip install -r requirements.txt

Conda and pip Conflict

# Always install conda packages FIRST, then pip-only packages
conda install numpy pandas scikit-learn
pip install some-pip-only-package

# Never install a conda package with pip or vice versa
# If things break, recreate from environment.yml
conda env remove --name myproject
conda env create -f environment.yml

"Externally Managed Environment" Error (PEP 668)

# Python 3.11+ on Debian/Ubuntu protects the system Python
# Solution: always use a virtual environment
python3 -m venv .venv
source .venv/bin/activate
pip install requests    # works fine inside the venv

# Or use pipx for global CLI tools
pipx install black
pipx install ruff

Frequently Asked Questions

What is the difference between venv and virtualenv?

venv is the built-in virtual environment module included in Python 3.3 and later. It requires no extra installation. virtualenv is a third-party package that predates venv and works with Python 2 and 3. virtualenv is faster at creating environments and has additional features like seed packages. For most modern Python 3 projects, venv is sufficient. Use virtualenv if you need Python 2 support or its advanced features.

Should I commit my virtual environment folder to Git?

No, never commit a virtual environment folder to version control. They contain platform-specific binaries and can be hundreds of megabytes. Instead, commit your requirements.txt, Pipfile, pyproject.toml, or poetry.lock file so that others can recreate the environment. Add .venv/ to your .gitignore file.

How do I choose between pipenv, Poetry, and plain pip with venv?

Use plain pip with venv for simple scripts and small projects. Use pipenv for applications where you want automatic environment management and a lock file. Use Poetry for libraries or applications needing robust dependency resolution and the ability to build and publish packages. Poetry is the most feature-complete option and the community standard for serious Python projects in 2026.

Why does activating a virtual environment not work in my IDE?

Most IDEs have their own interpreter selection mechanism. In VS Code, press Ctrl+Shift+P and search for "Python: Select Interpreter," then choose .venv/bin/python. In PyCharm, go to Settings → Project → Python Interpreter and add the interpreter from your virtual environment. The integrated terminal should activate automatically once the IDE knows about the environment.

Can I use conda and pip together in the same environment?

Yes, but with caution. Install as many packages as possible with conda first, then use pip only for packages not in conda channels. Never use pip to install a package previously installed with conda. If you mix the two, conda may not track pip-installed packages correctly, causing dependency conflicts during future updates.

How do I manage multiple Python versions on the same machine?

Use pyenv to install and switch between versions. Run pyenv install 3.12.1, then pyenv global 3.12.1 for the default or pyenv local 3.11.7 in a project directory. Once the desired version is active, create a venv with python -m venv .venv and it will use that version. Conda also manages multiple Python versions within its environments.

Conclusion

Virtual environments are not optional in Python development — they are a fundamental practice that every project should use from day one. The barrier to entry is zero: python -m venv .venv && source .venv/bin/activate takes five seconds and immediately gives you isolated dependency management.

For beginners, start with venv and pip. Once comfortable, graduate to Poetry for its superior dependency resolution and lock file support. If you work in data science, embrace conda for managing complex native dependencies. And if you maintain projects across multiple Python versions, pyenv is indispensable.

The most important takeaway: never install project dependencies globally. Every project gets its own environment. Every environment is documented in a requirements or lock file. Every environment is disposable and reproducible. Follow these principles and you will avoid the dependency conflicts that plague developers who skip this step.

⚙ Keep learning: Master data analysis with our Python Pandas Complete Guide, automate tasks with the Bash Scripting Complete Guide, and reference Python syntax with our Python Cheat Sheet.

Related Resources

Related Resources

Python Pandas Guide
Master DataFrames, groupby, merging, and data analysis
Bash Scripting Guide
Automate environment setup and deployment scripts
Python Beginners Guide
Learn Python fundamentals from variables to functions
Python Cheat Sheet
Quick reference for Python syntax and built-in methods
TOML Complete Guide
Understand the pyproject.toml configuration format
JSON Formatter
Format and validate Pipfile.lock and config files