Skip to content
  • Virtual Environments, pip & Packaging · Python

Virtual Environments, pip & Packaging

LearnViaNotes @learnvianotes· 4 min read

Isolate each project's dependencies in a virtual environment, pin them for reproducible installs, and describe your own project in pyproject.toml so it can be installed and published.

The venv lifecycle

Terminal
$ python3 -m venv .venv                   # create (once per project; don't commit it)
$ source .venv/bin/activate               # activate — Windows: .venv\Scripts\activate
(.venv) $ which python                    # → /path/to/project/.venv/bin/python
(.venv) $ python -m pip install --upgrade pip
(.venv) $ pip install "requests>=2.31" pytest
(.venv) $ deactivate                      # back to the system Python
$ rm -rf .venv                            # environments are disposable: delete & recreate
Python
import sys
print("inside a venv:", sys.prefix != sys.base_prefix)   # True inside a venv, False otherwise
print(sys.version_info >= (3, 10))                      # True

pip essentials

CommandDoes
pip install pkgInstall the latest compatible version (plus dependencies)
pip install "pkg==1.4.2"Install an exact version
pip install -U pkgUpgrade
pip uninstall pkgRemove (dependencies stay installed)
pip list / pip list --outdatedWhat's installed / what can be upgraded
pip show pkgVersion, location, dependencies of one package
pip freeze > requirements.txtExact versions of everything installed
pip install -r requirements.txtInstall from a requirements file
pip install -e .Editable install of the current project

Version specifiers

SpecifierMeans
==1.4.2Exactly 1.4.2
>=1.4,<2At least 1.4, below 2.0
~=1.4.2Compatible release: >=1.4.2, ==1.4.*
~=1.4>=1.4, ==1.* (i.e. below 2.0)
!=1.5.0Anything except 1.5.0
requests[socks]Install with an optional extra
tomli; python_version < "3.11"Environment marker — only on older Pythons

requirements.txt vs lock files

pyproject.toml

pyproject.toml
[project]
name = "lvn-notes"
version = "0.3.0"
description = "Study notes toolkit"
readme = "README.md"
requires-python = ">=3.10"
dependencies = ["requests>=2.31", "rich~=13.7"]

[project.optional-dependencies]
dev = ["pytest>=8", "mypy", "ruff"]

[project.scripts]
lvn = "lvn_notes.cli:main"          # installs an `lvn` command

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.ruff]
line-length = 100

It's plain TOML, so the standard library can read it:

Python
import tomllib

text = """
[project]
name = "lvn-notes"
requires-python = ">=3.10"
dependencies = ["requests>=2.31", "rich~=13.7"]
[project.scripts]
lvn = "lvn_notes.cli:main"
"""
meta = tomllib.loads(text)["project"]
print(meta["name"], meta["dependencies"])   # lvn-notes ['requests>=2.31', 'rich~=13.7']
print(tomllib.loads(text)["project"]["scripts"]["lvn"])   # lvn_notes.cli:main

Project layout, editable installs & publishing

src layout
lvn-notes/
├── pyproject.toml
├── README.md
├── src/
│   └── lvn_notes/
│       ├── __init__.py
│       └── cli.py
└── tests/
    └── test_cli.py
Terminal
(.venv) $ pip install -e ".[dev]"      # editable: code changes apply without reinstalling
(.venv) $ python -m pip install build twine
(.venv) $ python -m build              # → dist/lvn_notes-0.3.0.tar.gz and .whl
(.venv) $ twine upload dist/*          # publish to PyPI (use TestPyPI first)
ArtifactWhat it is
sdist (.tar.gz)Source distribution — built on the user's machine
wheel (.whl)Pre-built zip that installs by just unpacking — fast; platform-specific if it contains C extensions

The tool landscape

ToolRole
venv + pipBuilt in. Enough for most projects
uvVery fast Rust replacement for pip / venv / pip-tools; manages Python versions and uv.lock (uv add, uv run)
PoetryDependency management + lock file + build/publish in one tool
pipxInstalls CLI applications (black, httpie) each in its own isolated venv
condaEnvironments with non-Python binaries too (CUDA, MKL) — popular in data science
pyenvInstall and switch between several Python versions
pip-toolspip-compile turns loose requirements.in into pinned requirements.txt

Why use a virtual environment?

What is the difference between pip freeze output and pyproject.toml dependencies?

What does pip install -e . do?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report