skip to content

Essential Python Packages

Overview of the 34 most useful Python packages — HTTP clients, data science, web frameworks, orchestration, testing, and tooling. Each has its own dedicated page with examples.

15 min read 37 snippets deep dive

Essential Python Packages#

Each entry below links to a dedicated page with purpose, install command, code examples, outputs, and common pitfalls.

HTTP & Networking#

PackageInstallPurpose
requestspip install requestsSync HTTP client — the classic choice
httpxpip install httpxModern sync + async HTTP client

Data Science & Numerics#

PackageInstallPurpose
numpypip install numpyN-dimensional arrays and vectorized math
pandaspip install pandasDataFrames for tabular data
polarspip install polarsFast DataFrames with an expression API — 5–10× faster than pandas
modinpip install modin[ray]Drop-in pandas replacement that parallelises with Ray or Dask
matplotlibpip install matplotlib2-D plotting and figure generation
scipypip install scipyScientific algorithms (stats, optimize, signal)
pillowpip install pillowImage reading, transformation, and saving

Async & Concurrency#

PackageInstallPurpose
asyncio(stdlib — no install)Built-in async/await event loop

Standard Library Highlights#

PackageInstallPurpose
pathlib(stdlib — no install)Object-oriented filesystem path handling

CLI & Interfaces#

PackageInstallPurpose
clickpip install clickDecorator-based CLI builder
typerpip install typerType-hint-driven CLI builder built on Click
richpip install richTerminal formatting, tables, progress bars
tqdmpip install tqdmProgress bars for loops, downloads, and pipelines

Data Validation & Modeling#

PackageInstallPurpose
pydanticpip install pydanticRuntime type validation with Python type hints

Databases#

PackageInstallPurpose
sqlalchemypip install sqlalchemyORM + SQL toolkit for Python
sqlmodelpip install sqlmodelTyped ORM built on SQLAlchemy + Pydantic, designed for FastAPI
duckdbpip install duckdbEmbedded analytics DB — query CSV/Parquet directly with SQL

Web Frameworks#

PackageInstallPurpose
flaskpip install flaskLightweight WSGI micro-framework
djangopip install djangoFull-featured batteries-included framework
fastapipip install fastapiFast ASGI API framework with auto-docs
litestarpip install litestarHigh-performance ASGI framework with strict typing
reflexpip install reflexFull-stack web apps in pure Python — compiles to React

Workflow & Orchestration#

PackageInstallPurpose
prefectpip install prefectWorkflow orchestration with @flow/@task decorators and a built-in UI
dagsterpip install dagsterAsset-centric data orchestration with software-defined assets

Logging#

PackageInstallPurpose
logurupip install loguruStructured logging with zero configuration

Notebooks & Interactive#

PackageInstallPurpose
jupyterpip install jupyterlabInteractive notebooks for data exploration

Testing#

PackageInstallPurpose
pytestpip install pytestTest discovery, fixtures, and parametrize

Type Checking#

PackageInstallPurpose
mypypip install mypyStatic type checker

Code Quality & Formatting#

PackageInstallPurpose
ruffpip install ruffFast all-in-one linter and formatter (replaces black + flake8 + isort)
blackpip install blackOpinionated code formatter

Packaging & Dependency Management#

PackageInstallPurpose
uvcurl -LsSf https://astral.sh/uv/install.sh | shBlazing-fast installer and project manager
poetrypip install poetrypyproject.toml-based dependency management and publishing

Quick decision guide#

  • New project, greenfield? → Use uv for environment + deps, ruff for linting, pytest for tests, pydantic for validation.
  • Building a REST API?fastapi + pydantic + sqlalchemy; use litestar for higher throughput.
  • Quick internal tool?flask (small) or django (if you need admin/auth out of the box).
  • Full-stack with no JS?reflex — Python-only, compiles to React.
  • Data analysis script?pandas + matplotlib; switch to polars for larger datasets or speed.
  • Large-scale data (>1 GB)?polars (fastest) or modin (pandas drop-in with parallelism).
  • Analytics SQL on files?duckdb — query CSV/Parquet directly, no server needed.
  • HTTP calls?requests for sync, httpx for async or when you want HTTP/2.
  • CLI tool?typer (type-hint-driven) or click (decorator-based).
  • Progress bars?tqdm — wraps any iterable in one line.
  • Logging?loguru for new projects; it replaces logging with zero boilerplate.
  • Data exploration?jupyter + pandas + matplotlib — run cells interactively.
  • Async concurrency?asyncio (stdlib) + httpx for async HTTP or fastapi for async APIs.
  • Scheduled workflows / ETL?prefect (function-centric) or dagster (asset-centric).
  • Typed ORM for FastAPI?sqlmodel — combines SQLAlchemy and Pydantic.
  • File paths?pathlib (stdlib) — never use os.path.join() again.

The modern Python toolchain (2026)#

A single recommended stack for new projects. Every piece on this list replaces 2–4 older tools and reduces configuration to a single pyproject.toml.

ConcernPickReplaces
Package manageruvpip + pip-tools + virtualenv + pyenv + pipx
Lint + formatruffflake8 + isort + black + pylint + bandit
Type checkermypy (or pyright)
Test runnerpytestunittest
Data validationpydanticdataclasses + custom validators
HTTP clienthttpxrequests + aiohttp
CLItyperclick + argparse
Logginglogurulogging stdlib
ORMsqlalchemy 2.xDjango ORM, peewee, SQLObject

The whole stack installs in under 5 seconds with uv:

uv init myapp && cd myapp
uv add httpx pydantic typer loguru sqlalchemy
uv add --dev pytest ruff mypy

Output:

Initialized project `myapp` at `/home/alice/myapp`
Resolved 24 packages in 320ms
Installed 24 packages in 95ms

A minimal pyproject.toml for this stack:

[project]
name = "myapp"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
    "httpx>=0.27",
    "pydantic>=2",
    "typer>=0.12",
    "loguru>=0.7",
    "sqlalchemy>=2",
]

[tool.uv]
dev-dependencies = [
    "pytest>=8",
    "ruff>=0.5",
    "mypy>=1.10",
]

[tool.ruff]
line-length = 100
target-version = "py312"

[tool.ruff.lint]
select = ["E", "F", "I", "B", "UP", "C4", "SIM", "RUF"]

[tool.mypy]
strict = true
python_version = "3.12"

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-ra --strict-markers"

Run everything with one command via a Makefile or [tool.poe.tasks]:

uv run ruff check .
uv run ruff format .
uv run mypy src
uv run pytest -v

How to evaluate a Python package#

Before adding a dependency, run through this checklist. A bad pick adds risk that lingers for years — outdated deps, abandoned maintenance, security holes, lock-in.

1. Health signals#

  • Recent commits: git log --since="6 months ago" on the upstream repo. Anything older than 12 months without releases is a warning sign.
  • Open issues vs PRs: a healthy project closes most issues within weeks; thousands of stale issues with no triage suggests abandonment.
  • Release cadence: predictable monthly or quarterly releases beat sporadic year-long gaps.
  • GitHub stars and forks: imperfect but useful for triangulating popularity. Cross-check against PyPI download counts.
# Download stats — pypistats CLI
pipx install pypistats
pypistats recent fastapi
pypistats overall fastapi --start-date 2024-01-01

# Bus factor — distinct contributors in the last year
gh repo view encode/httpx --json contributors

2. PyPI metadata#

pip show or pip index versions surfaces facts that don’t appear on GitHub.

pip show fastapi                       # local install info
pip index versions fastapi             # all available versions

Output:

fastapi (0.111.1)
Available versions: 0.111.1, 0.111.0, 0.110.3, 0.110.2, ...

Check for: a LICENSE (or the license is listed in classifiers), a non-zero Requires-Python, and a Project-URL pointing to a real repo.

3. Typing and stubs#

A typed library catches bugs at write time and unlocks editor autocompletion. Check for:

  • A py.typed marker file in the package (signals inline type hints).
  • A separate <pkg>-stubs package on PyPI.
  • Programming Language :: Python :: Implementation :: CPython plus Typing :: Typed classifiers.
pip download --no-deps --no-binary :all: fastapi
tar tzf fastapi-*.tar.gz | grep py.typed

4. Dependency footprint#

Every dependency is itself a dependency you take on. A package that pulls in 30 transitive deps for a small feature is a red flag.

uv add --dry-run fastapi       # uv shows the full graph without installing
pipdeptree --packages fastapi  # in an existing venv

For libraries especially, prefer single-purpose packages with minimal dependencies.

5. Security#

pip install pip-audit
pip-audit                       # scan installed packages for CVEs
pip-audit -r requirements.txt   # scan a requirements file

# uv-native equivalent
uvx pip-audit

Cross-reference osv.dev and PyPI’s advisory database for any package you depend on.

6. Compatibility horizon#

Check the package’s declared Requires-Python and the version of its core dependencies. A package that still pins pydantic<2 in 2026, for example, will block you from upgrading the rest of your stack.

pip show pydantic | grep "^Requires:"

7. License compatibility#

The vast majority of PyPI is MIT, BSD, or Apache 2.0 — friendly for any use case. Watch for GPL/LGPL/AGPL packages if you ship proprietary software: they may force your codebase to be open source. Verify with pip-licenses:

uvx pip-licenses --format=markdown --with-urls

Curated lists by use case#

Web — REST API#

uv add fastapi "uvicorn[standard]" pydantic
uv add --dev pytest httpx pytest-asyncio

Stack: fastapi routes + pydantic request/response models + uvicorn ASGI server. For higher throughput swap fastapi for litestar. For traditional MVC web apps use django.

Web — full-stack without JavaScript#

uv add reflex
uv run reflex init && uv run reflex run

reflex compiles Python to React — a single language for both frontend and backend.

Data — analysis and exploration#

uv add pandas matplotlib jupyter
uv run jupyter lab

Stack: pandas DataFrames, matplotlib plots, jupyter notebook UI. For datasets too large for pandas (>1 GB or >10M rows) switch to polars.

Data — scientific computing#

uv add numpy scipy matplotlib

numpy arrays form the substrate; scipy adds stats/optimize/signal modules. pillow for image I/O.

Data — large-scale analytics on files#

uv add duckdb polars

duckdb queries CSV/Parquet/JSON with SQL — no server, no schema. polars provides a pandas-like API with lazy evaluation and multi-core execution.

CLI tools#

uv add typer rich tqdm
uv add --dev pytest

typer for command parsing, rich for styled output and tables, tqdm for progress bars. For decorator-style CLI prefer click (typer is built on top of click).

HTTP clients#

uv add httpx        # modern, sync + async, HTTP/2
# or
uv add requests     # battle-tested, sync only

httpx is the default for new code. requests remains supported and is the right choice for legacy integration.

Async#

uv add httpx fastapi

asyncio is stdlib. Pair with httpx for HTTP and fastapi for web. Don’t mix sync requests calls into async code — block the loop.

ETL / data orchestration#

uv add prefect       # function-centric @flow/@task
# or
uv add dagster       # asset-centric, software-defined assets

prefect suits ad-hoc pipelines and quick prototypes. dagster is stricter and excels for declarative data platforms.

Database access#

uv add "sqlalchemy>=2" alembic    # general
uv add sqlmodel                    # FastAPI projects
uv add duckdb                      # analytics on local files

sqlalchemy is the standard ORM + SQL toolkit. sqlmodel merges SQLAlchemy and Pydantic for FastAPI. alembic (a SQLAlchemy plugin) handles migrations.

Testing#

uv add --dev pytest pytest-cov pytest-xdist httpx

pytest is non-negotiable. pytest-cov for coverage; pytest-xdist for parallel test runs; httpx’s test client for HTTP integration tests.

Code quality#

uv add --dev ruff mypy

ruff replaces flake8, isort, black, pylint, bandit, and pyupgrade with a single Rust binary. mypy (or pyright) catches type errors. Skip black for new projects — ruff format is bit-identical.

Logging#

uv add loguru

loguru replaces logging with zero configuration: structured output, color, file rotation, exception tracebacks. Use stdlib logging only when integrating with frameworks that already wire it up.

Notebooks#

uv add jupyterlab ipython
uv run jupyter lab

jupyter for interactive notebooks; ipython is the enhanced REPL beneath them.

Build, package, and ship#

uv add --dev build twine        # legacy
# or just use uv directly
uv build && uv publish

uv replaces both build and twine. Use poetry if your team prefers its workflow. See pyproject.toml for the canonical project config.

When the stdlib is enough#

A surprising amount of Python doesn’t need a third-party dependency. Reach for stdlib first when:

TaskStdlib module
File pathspathlib.Path
JSONjson
CSVcsv
HTTP serverhttp.server
Async runtimeasyncio
HTTP clienturllib.request (small scripts)
Date/timedatetime, zoneinfo
Subprocesssubprocess
Argument parsingargparse
Logginglogging
Templatingstring.Template
Hashinghashlib
Compressiongzip, zipfile, tarfile
Emailemail.message
HTML parsinghtml.parser
SQLsqlite3
Concurrencyconcurrent.futures
Testingunittest
Type stubstyping
Data classesdataclasses
Enumsenum
Randomrandom, secrets
Statisticsstatistics

Pull in a third-party package when the stdlib equivalent is too verbose, missing a feature (e.g., urllib has no streaming), or the community has clearly converged on a better tool (e.g., pydantic over manual dataclass validation).

Migration paths#

If you’re on an older stack, here’s the modern replacement.

FromToWhy
requestshttpxSame API, also async, HTTP/2
flake8 + isort + black + pylintruff100× faster, single binary
pip + virtualenv + pyenvuv10–100× faster, single tool
logging boilerplateloguruZero-config structured logs
argparsetyper or clickType-hint-driven, auto-help
unittestpytestFixtures, parametrize, plugins
dataclasses validationpydanticRuntime validation, error messages
pandas (large data)polars5–10× faster, lazy evaluation
aiohttp clienthttpx.AsyncClientSame API as sync client
setup.pypyproject.tomlPEP 621, modern tooling
toxnox or uv matrixPython config, faster
pipenvuv or poetryMaintained, faster

Common pitfalls#

[!WARNING] Installing libraries globallypip install <pkg> outside a venv puts packages on the system Python and can break OS tools. Always activate a venv first, or use uv tool install / pipx for CLIs.

[!WARNING] Pinning every dependency in a library — applications should pin tightly (via uv.lock / poetry.lock). Libraries should pin loosely (e.g., httpx>=0.27) so they compose with other libraries.

[!WARNING] Treating pip freeze > requirements.txt as a lockfilepip freeze captures everything currently installed, including packages you’ve forgotten about. Use uv lock or pip-compile instead.

[!WARNING] Mixing async and sync HTTP librariesrequests calls inside an async def block the event loop. Use httpx.AsyncClient or aiohttp in async code.

[!TIP] Add pip-audit or uvx pip-audit to CI — it scans installed packages against the OSV vulnerability database and catches CVEs before they ship.

[!TIP] Add ruff check --select=ALL once in a fresh project, then narrow down the noisy rules. Ruff has the largest rule catalog of any Python linter; you only need a curated subset.

Real-world recipes#

Recipe — small CLI with subcommands#

uv init my-cli
cd my-cli
uv add typer rich
uv add --dev pytest
# my_cli/main.py
import typer
from rich import print

app = typer.Typer()

@app.command()
def hello(name: str = "world"):
    print(f"[bold green]Hello, {name}![/]")

@app.command()
def list_items(verbose: bool = False):
    items = ["alpha", "beta", "gamma"]
    if verbose:
        print(items)
    else:
        for it in items:
            print(it)

if __name__ == "__main__":
    app()

Recipe — async scraper with httpx + tqdm#

uv add httpx tqdm
import asyncio, httpx
from tqdm.asyncio import tqdm

async def fetch(client, url):
    r = await client.get(url)
    return r.status_code

async def main():
    urls = [f"https://httpbin.org/anything/{i}" for i in range(50)]
    async with httpx.AsyncClient() as client:
        tasks = [fetch(client, u) for u in urls]
        results = await tqdm.gather(*tasks)
    print({r: results.count(r) for r in set(results)})

asyncio.run(main())

Recipe — REST API with FastAPI + SQLModel#

uv add fastapi "uvicorn[standard]" sqlmodel
uv add --dev pytest httpx
from fastapi import FastAPI
from sqlmodel import SQLModel, Field, Session, create_engine, select

class User(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str
    email: str

engine = create_engine("sqlite:///./app.db")
SQLModel.metadata.create_all(engine)

app = FastAPI()

@app.post("/users")
def create_user(user: User) -> User:
    with Session(engine) as s:
        s.add(user); s.commit(); s.refresh(user)
        return user

@app.get("/users")
def list_users() -> list[User]:
    with Session(engine) as s:
        return list(s.exec(select(User)))

Recipe — data ETL with pandas + duckdb#

uv add pandas duckdb
import duckdb, pandas as pd

# Query 10 GB of Parquet without loading it all into RAM
df = duckdb.sql("""
    SELECT user_id, SUM(amount) AS total
    FROM 'sales/*.parquet'
    WHERE event_date >= '2026-01-01'
    GROUP BY user_id
    HAVING total > 1000
""").df()

print(df.head())

Recipe — typed configuration with pydantic-settings#

uv add pydantic pydantic-settings
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    database_url: str
    redis_url: str = "redis://localhost:6379"
    debug: bool = False

    class Config:
        env_file = ".env"

settings = Settings()
print(settings.database_url)

Where to look next#

  • pyproject.toml — declare metadata and deps once, used by every modern tool.
  • uv — the recommended package manager in 2026.
  • pip — universal fallback; understand it even if you use uv.
  • venv — stdlib environment isolation, no extra tools required.
  • poetry — full-featured alternative for existing teams.
  • pip vs uv — side-by-side comparison with migration guide.