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?)
Machine learning engineer in Tokyo. Developing Speeda AI Agent (with A2A) [1]
@ftnext SpeechRecognition (9kβοΈ) maintainer
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π
We've reached an agreement to acquire Astral.
β OpenAI Newsroom (@OpenAINewsroom) 2026εΉ΄3ζ19ζ₯
After we close, OpenAI plans for @astral_sh to join our Codex team, with a continued focus on building great tools and advancing the shared mission of making developers more productive.https://t.co/V0rDo0G8h9
Breaking Free from Virtual Environments: Agenda
Virtual Environment Basics (quickπββοΈ)
The Pain of Manual Virtual Environment Management (quickπββοΈ)
Evolution of Solutions (Main Part)
Solutions Available as of 2026
CLI execution using temporary virtual environments
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
A virtual environment is a directory
% python -m venv --help
usage: venv ENV_DIR [ENV_DIR ...]
.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]
.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
easter egg: πthon https://github.com/python/cpython/pull/125035
.venv/bin/python
A symbolic link to the Python interpreter installed on your machine
The
activatescript updates thePATHenvironment variable so this interpreter is foundThe 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
There are two types of dependencies
(.venv) $ % python -m pip install httpx
(.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.txtIf extras were specified for direct dependencies [3], extra information is lost in
requirements.txt
Example: python -m pip install SpeechRecognition[audio]
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
Problem 3: Virtual environments proliferate per script
Just want to quickstart a library, but a new virtual environment must be created each time
.
βββ .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
pip freezelumps direct and transitive togetherCan we remove transitive when removing direct?
Too many virtual environments for scripts
Installing and updating CLIs in every virtual environment
3οΈβ£ How the Community Has Addressed These Problems
pip freezelumps direct and transitive togetherCan we remove transitive when removing direct?
Too many virtual environments for scripts
Installing and updating CLIs in every virtual environment
pip-tools
In place of
pip freeze: pip-compile & pip-sync [4]
https://github.com/jazzband/pip-tools/blob/v7.5.3/img/pip-tools-overview.svg
pip-tools workflow
requirements.inhttpx
Problem 1: direct and transitive lumped together β solved
pip-tools workflow
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.txtChange direct dependencies in
requirements.into update bothrequirements.txtand the virtual environment (Problem 2 solved)
Poetry
$ poetry new
$ poetry add httpx
$ ls
poetry.lock pyproject.toml
Even less awareness of virtual environments [5]
poetry run to run in the virtual environment$ poetry run python -m pip freeze
Widely adopted for Python project development (around 2020) [6]
use the {project-dir}/.venv directory if one already exists.
Pipenv was also widely adopted for Python project development
Rye [7]
Written in Rust (faster than Python-based tools)
Python version management + virtual environment management
$ rye init
$ rye add httpx
$ rye sync
Created by mitsuhiko, transferred to Astral, then archived in February 2026. Thank you for the great work.
It was technically interesting that it managed virtual environments without pip, using pip-tools
And then came uv
Emerged as a Rust implementation of pip. drop-in replacement for pip and pip-tools workflows.
Expanded to also manage Python itself and project virtual environments [9]
$ 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
curl -LsSf https://astral.sh/uv/install.sh | sh
brew [12]python3 -m pip install --user pipx
For detail, see https://pipx.pypa.io/stable/how-to/install-pipx/#installing-pipx
The tool installs into a temporary virtual environment
Not creating a new virtual environment every time β it's also cached https://docs.astral.sh/uv/concepts/tools/#tool-environments
https://pipx.pypa.io/stable/explanation/how-pipx-works/#pipx-run
Demo Manual venv vs uvx
$ python -m venv format-env --upgrade-deps
$ source format-env/bin/activate
(format-env) $ python -m pip install ruff
(format-env) $ ruff format
$ 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 run build
$ pipx run twine check dist/*
https://github.com/ftnext/sphinx-new-tab-link/blob/v0.8.1/.github/workflows/publish.yml
FYI: You can also install globally on your machine
uv tool install
pipx install (Installing stand alone command line tools)
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
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]
# /// script
# requires-python = ">=3.13"
# dependencies = [
# "httpx",
# "rich",
# ]
# ///
The author of PEP 723 is the creator of Hatch
Just run with a tool that supports inline script metadata
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",
# ]
# ///
uv init --script creates an empty script with inline script metadata
Lower bounds are written starting from uv 0.9.16. ref: https://github.com/astral-sh/uv/issues/15544
Demo Manual venv vs uv run script.py
$ 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
$ 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]
uv run https://gist.githubusercontent.com/ftnext/d9a2094ca2a54e84d3677217e607c783/raw/5438023012cef1957801b95b6b9685d0a0e01e6f/unlock_pdf.py (not recommended for scripts you don't trust)
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 runin the shebang) [25]
Example: https://github.com/argilla-io/synthetic-data-generator/pull/23
with cchooks https://gist.github.com/ftnext/ccc020832e1d753554428ff520c3ea49
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π
pyproject.toml)$ uv add httpx
$ uv sync
Currently the top choice for broadly supporting everything from
uvxto 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