Breaking Free from Virtual Environments: A New Python Paradigm for 2026

Breaking Free from Virtual Environments: A New Python Paradigm for 2026

Event:

PythonAsia 2026

Presented:

2026/03/22 nikkie

Hello, PythonAsia! (Who are you?)

../_images/uzabase-white-logo.png

What is something developers used to manage themselves all the time, but hardly manage anymore?

The answer is virtual environments

Hard to believe? πŸ™‹

many developers no longer need to manage virtual environments directly

  • Various Python project management tools

  • CLI execution using temporary virtual environments

  • inline script metadata (PEP 723)

may affect this landscapeπŸ˜…

Breaking Free from Virtual Environments: Agenda

  1. Virtual Environment Basics (quickπŸƒβ€β™‚οΈ)

  2. The Pain of Manual Virtual Environment Management (quickπŸƒβ€β™‚οΈ)

  3. Evolution of Solutions (Main Part)

Solutions Available as of 2026

  1. CLI execution using temporary virtual environments

  2. inline script metadata (PEP 723)

1️⃣ Virtual Environment Basics

Why do we (Python developers) need virtual environments?

From the Python Tutorial

$ python -m venv .venv --upgrade-deps
$ source .venv/bin/activate
(.venv) $ python -m pip install sampleproject

12.2. Creating Virtual Environments (The Python Tutorial)

A virtual environment is a directory

% python -m venv --help
usage: venv ENV_DIR [ENV_DIR ...]
A directory called .venv/ has been created
% ls -al
drwxr-xr-x@  7 nikkie  staff  224 Mar 20 12:42 .venv

Why create a directory?

  • To serve as the installation destination for third-party libraries

  • Without a virtual environment, there is only one installation location on the machine

What's inside .venv/? [2]

Installed on macOS from python.org
.venv
β”œβ”€β”€ bin
β”‚   β”œβ”€β”€ activate
β”‚   β”œβ”€β”€ pip
β”‚   β”œβ”€β”€ pip3
β”‚   β”œβ”€β”€ pip3.14
β”‚   β”œβ”€β”€ python -> python3.14
β”‚   β”œβ”€β”€ python3 -> python3.14
β”‚   β”œβ”€β”€ python3.14 -> /Library/Frameworks/Python.framework/Versions/3.14/bin/python3.14
β”‚   └── πœ‹thon -> python3.14
β”œβ”€β”€ lib
β”‚   └── python3.14/
└── pyvenv.cfg

.venv/bin/python

  • A symbolic link to the Python interpreter installed on your machine

  • The activate script updates the PATH environment variable so this interpreter is found

  • The interpreter and standard library use this path

.venv/lib/python3.14/site-packages/

  • The directory where third-party libraries are installed

  • Separated per virtual environment, so different versions can coexist

2️⃣ We Are the Virtual Environment Management Tool

$ python -m venv .venv --upgrade-deps
$ source .venv/bin/activate
(.venv) $ python -m pip install sampleproject

Let's list the pains of manual management (4 in total)

Reproducing a virtual environment: pip freeze

(.venv) $ python -m pip freeze > requirements.txt
$ python -m venv recreate-env --upgrade-deps
$ source recreate-env/bin/activate
(recreate-env) $ python -m pip install -r requirements.txt

12.3. Managing Packages with pip (The Python Tutorial)

There are two types of dependencies

Direct dependencies
(.venv) $ % python -m pip install httpx
Transitive dependencies
(.venv) $ python -m pip freeze
anyio==4.12.1
certifi==2026.2.25
h11==0.16.0
httpcore==1.0.9
httpx==0.28.1
idna==3.11

Problem 1: pip freeze output is hard to manage

  • Both direct and transitive dependencies are combined into a single requirements.txt

  • If extras were specified for direct dependencies [3], extra information is lost in requirements.txt

Problem 2: Hard to uninstall specific packages

  • When removing a direct dependency, removing transitive dependencies is difficult

  • Direct dependency 1 depends on libA and libB

  • Direct dependency 2 depends on libA and libC

../_images/remove-direct-dependency-en.drawio.png

Problem 3: Virtual environments proliferate per script

  • Just want to quickstart a library, but a new virtual environment must be created each time

Many directories like this
.
β”œβ”€β”€ .venv/
└── script.py

Problem 4: Linters and formatters installed in every virtual environment

  • CLIs used during development must be installed in every virtual environment

  • Keeping them up to date across all projects is less convenient

Our Pain as Virtual Environment Managers

  1. pip freeze lumps direct and transitive together

  2. Can we remove transitive when removing direct?

  3. Too many virtual environments for scripts

  4. Installing and updating CLIs in every virtual environment

3️⃣ How the Community Has Addressed These Problems

  1. pip freeze lumps direct and transitive together

  2. Can we remove transitive when removing direct?

  3. Too many virtual environments for scripts

  4. Installing and updating CLIs in every virtual environment

pip-tools

  • In place of pip freeze: pip-compile & pip-sync [4]

../_images/pip-tools-overview.svg

pip-tools workflow

Write direct dependencies in requirements.in
httpx

Problem 1: direct and transitive lumped together β€” solved

pip-tools workflow

pip-compile generates requirements.txt (direct & transitive)
anyio==4.12.1
    # via httpx
certifi==2026.2.25
    # via
    #   httpcore
    #   httpx
h11==0.16.0
    # via httpcore
httpcore==1.0.9
    # via httpx
httpx==0.28.1
    # via -r requirements.in
idna==3.11
    # via
    #   anyio
    #   httpx

pip-tools workflow

  • Use pip-sync to sync the virtual environment to requirements.txt

  • Change direct dependencies in requirements.in to update both requirements.txt and the virtual environment (Problem 2 solved)

Poetry

Specify direct dependencies (= approach to Problems 1 & 2)
$ poetry new
$ poetry add httpx
$ ls
poetry.lock     pyproject.toml

Even less awareness of virtual environments [5]

Just prefix commands with poetry run to run in the virtual environment
$ poetry run python -m pip freeze
  • Widely adopted for Python project development (around 2020) [6]

Rye [7]

  • Written in Rust (faster than Python-based tools)

  • Python version management + virtual environment management

$ rye init
$ rye add httpx
$ rye sync

And then came uv

$ uv init
$ uv add httpx
$ uv sync

The path to uv

  • Poetry (and Pipenv) made Python project virtual environment management easy

  • Rust-based Rye: also manages Python itself (virtual env management via pip-tools)

  • uv incorporated Rye's features along with pipx and PEP 723 (introduced next)

3️⃣-1️⃣ CLI Execution Without Virtual Environment Management

  • Approach to Problem 4: "Installing and updating CLIs in every virtual environment"

  • Using Ruff as an example, but applicable to any CLI on PyPI

Before: Install to virtual environment, then run CLI

$ # python -m venv .venv --upgrade-deps
$ source .venv/bin/activate  # project's virtual environment
(.venv) $ python -m pip install ruff
(.venv) $ ruff format

Now, CLI execution using temporary virtual environments is possible

  • uvx ruff format (uv tool run ruff format) [10]

  • or pipx run ruff format

Installation

uv (for macOS & Linux) [11]
curl -LsSf https://astral.sh/uv/install.sh | sh
For pipx, prefer your system's package manager like brew [12]
python3 -m pip install --user pipx

The tool installs into a temporary virtual environment

  • Sets up a temporary virtual environment with the package installed [13]

  • Runs the CLI [14]

Demo Manual venv vs uvx

Before
$ python -m venv format-env --upgrade-deps
$ source format-env/bin/activate
(format-env) $ python -m pip install ruff
(format-env) $ ruff format
After
$ uvx ruff format

Recommendations for uvx and pipx run

  • We don't touch virtual environments (the tool handles it)

  • Use the latest CLI version without management overhead

  • Works across multiple projects (Problem 4 solved)

Here's where I use it [15]

$ uvx cookiecutter gh:simonw/llm-plugin
$ uvx --from sphinx --with sphinx-new-tab-link \
    sphinx-build -M html source build
pipx is pre-installed on GitHub Actions Ubuntu images [16]
$ pipx run build
$ pipx run twine check dist/*

FYI: You can also install globally on your machine

However, manual upgrade is required (uv tool upgrade Β· pipx upgrade-all)

3️⃣-2️⃣ inline script metadata

  • Approach to Problem 3: "Too many virtual environments for scripts"

  • Applicable to any Python script

https://packaging.python.org/en/latest/specifications/inline-script-metadata/

A script using third-party libraries

Get the titles of the 10 most recent PEPs
from datetime import datetime

import httpx
from rich.pretty import pprint

resp = httpx.get("https://peps.python.org/api/peps.json")
data = resp.json()
peps_desc_created = sorted(
    data.items(),
    key=lambda item: datetime.strptime(item[1]["created"], "%d-%b-%Y"),
    reverse=True,
)
pprint([(k, v["title"], v["created"]) for k, v in peps_desc_created][:10])

Before: Install dependencies to virtual environment, then run script

$ python -m venv .venv --upgrade-deps
$ source .venv/bin/activate
(.venv) $ python -m pip install httpx rich
(.venv) $ python script.py

PEP 723 – Inline script metadata [17]

Write TOML-format metadata as comments
# /// script
# requires-python = ">=3.13"
# dependencies = [
#     "httpx",
#     "rich",
# ]
# ///

Just run with a tool that supports inline script metadata

  • uv run script.py

  • pipx run script.py

  • hatch run script.py [18]

  • pdm run script.py [19]

The tool sets up a virtual environment with dependencies installed and runs the script

  • The tool reads the metadata

  • Uses a Python interpreter matching requires-python

  • Sets up a temporary virtual environment with dependencies installed, then runs the script

uv can write inline script metadata! [20]

uv add --script script.py httpx rich [21]

# /// script
# requires-python = ">=3.13"
# dependencies = [
#     "httpx>=0.28.1",
#     "rich>=14.3.3",
# ]
# ///

Demo Manual venv vs uv run script.py

Before
$ python -m venv script-env --upgrade-deps
$ source script-env/bin/activate
(script-env) $ python -m pip install httpx rich
(script-env) $ python script.py
After [22]
$ uv add --script script.py httpx rich
$ uv run script.py

Recommendations for inline script metadata

  • We don't touch virtual environments (the tool handles it) (Problem 3 solved)

  • The script declares its own dependencies

  • Easy to reproduce and run on another machine [23]

Here's where I use it

  • When sharing scripts on Slack or Discord

  • Propose adoption in examples for libraries published on PyPI [24]

  • Hooks for coding agents (using uv run in the shebang) [25]

Finally, Tool Selection

Considering Python project management since Poetry

  • uvπŸ…

  • Hatch❀️

Poetry

  • Poetry made things much easier (but challenges around CLI and script execution remained)

  • Slower to adopt some newer specs (not my first recommendation)

uvπŸ…

Also supports Python project management (enforces pyproject.toml)
$ uv add httpx
$ uv sync
  • Currently the top choice for broadly supporting everything from uvx to inline script metadata with one tool (but watching OpenAI)

Hatch

  • Also supports Python project management, but manages multiple virtual environments

  • Can use inline script metadata, but lacks uvx-equivalent functionality

Hatch is interesting ❀️

$ hatch env show
Standalone
┏━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Name    ┃ Type    ┃ Dependencies ┃ Scripts ┃
┑━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━┩
β”‚ default β”‚ virtual β”‚              β”‚         β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ types   β”‚ virtual β”‚ mypy>=1.0.0  β”‚ check   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Most tools including uv use a single virtual environment per Python project

Summary 🌯 Breaking Free from Manual Virtual Environment Management

  • Virtual environments remain important as installation destinations for third-party libraries

  • However, today, many developers no longer need to manage virtual environments directly.

Developers are abstracted away from manual virtual environment management

  • CLI execution: tools install into a temporary virtual environment

  • Script execution: inline script metadata

Let's try it and make life easier!

  • uv (uvx, uv run)

  • pipx (pipx run)

Do beginner tutorials really need virtual environment setup commands?

  • Isn't it time to revisit Python tutorials and beginner books?

  • IMO: For beginners who just want to write scripts in Python, starting with inline script metadata might lower the barrier

  • Professional Python developers are still recommended to understand virtual environments

Thank you for listening

Happy Python Development