Skip to content
Red-Green Software

· 5 min read

Python: what it does best

Where Python shines, and a tour of the libraries we reach for most: requests, pendulum, pandas, Django, Jinja2, SQLAlchemy, Black, Pylint and pytest.

#python #languages #tools

Python is rarely the fastest language in the room, and it doesn’t need to be. Its strength is how little stands between an idea and working, tested code. Most of that strength comes from its libraries.

What Python does best

  • Automation and glue. Moving files, calling APIs, transforming data and stitching systems together. A Python script is often the shortest path from “we do this by hand” to “it just happens”.
  • Data work. Cleaning, analyzing and reporting on data, from a CSV export to a data warehouse.
  • Web back ends. Database-backed sites and APIs where developer time costs more than server time.
  • Science and machine learning. The de facto language of the field, with fast libraries written in C, C++ and Rust underneath.
  • Prototypes. Trying an idea quickly, then keeping the parts that work.
  • Teaching and readability. Code that reads close to plain English is code the next person can maintain.

Where it’s weaker: CPU-heavy pure-Python loops, mobile apps, and anywhere you need a single small binary. For those, see The right tool for the job.

The libraries we reach for

Requests: HTTP for humans

Requests makes calling a web API a one-liner. It handles sessions, cookies, redirects, authentication and JSON for you.

import requests

r = requests.get("https://api.github.com/repos/psf/requests", timeout=10)
r.raise_for_status()
print(r.json()["stargazers_count"])

Always pass a timeout: by default Requests will wait forever. If you need async or HTTP/2, look at HTTPX, which has a very similar API.

Pendulum: dates and times without tears

Pendulum is a drop-in replacement for the standard datetime that is time-zone-aware by default and makes arithmetic and formatting pleasant.

import pendulum

meeting = pendulum.datetime(2026, 11, 9, 14, 30, tz="America/New_York")
print(meeting.in_timezone("Europe/London"))  # 2026-11-09 19:30:00+00:00
print(meeting.add(weeks=2).to_date_string())  # 2026-11-23
print(meeting.subtract(days=3).diff_for_humans(meeting))  # 3 days before

For simple cases, the standard library’s zoneinfo module now covers time zones well. Pendulum earns its place when you do a lot of date arithmetic, parsing or human-friendly output.

pandas: spreadsheets in code

pandas gives you the DataFrame: a table you can load, filter, join, group and summarize in a few lines. It reads and writes CSV, Excel, JSON, SQL and Parquet.

import pandas as pd

sales = pd.read_csv("sales.csv")
by_region = sales.groupby("region")["total"].sum().sort_values(ascending=False)
print(by_region.head())

pandas holds everything in memory, so very large datasets can be slow. Polars is a fast, modern alternative worth knowing.

Django: the web framework with batteries included

Django gives you an ORM, database migrations, authentication, forms, security protections and an automatic admin site out of the box.

from django.db import models


class Post(models.Model):
    title = models.CharField(max_length=200)
    published = models.DateTimeField()


# Elsewhere: Post.objects.filter(published__year=2026).order_by("-published")

Choose Django for database-driven sites where you want the decisions made for you. For small services and APIs, Flask or FastAPI are lighter.

Jinja2: templates for anything

Jinja2 turns templates plus data into text: HTML pages, emails, config files, reports. Flask and Ansible use it, and its syntax inspired Tera, the template engine behind this very site.

from jinja2 import Template

t = Template(
    "Hello {{ name }}! You have {{ count }} new message{{ 's' if count != 1 }}."
)
print(t.render(name="Ada", count=3))  # Hello Ada! You have 3 new messages.

When rendering HTML, use an Environment with autoescape=True so user input can’t inject markup.

SQLAlchemy: databases, your way

SQLAlchemy is the standard toolkit for talking to SQL databases from Python. Use its Core layer to build SQL safely, or its ORM to map tables to classes. It works with PostgreSQL, MySQL, SQLite and more.

from sqlalchemy import create_engine, select, String
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session


class Base(DeclarativeBase):
    pass


class User(Base):
    __tablename__ = "users"
    id: Mapped[int] = mapped_column(primary_key=True)
    name: Mapped[str] = mapped_column(String(50))


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

with Session(engine) as session:
    session.add(User(name="Ada"))
    session.commit()
    print(session.scalars(select(User).where(User.name == "Ada")).one().id)

Pair it with Alembic for schema migrations when you’re not using Django’s own ORM.

Black: stop arguing about formatting

Black reformats your code to one consistent style with almost no options. That’s the point: formatting stops being a code-review topic.

black .           # reformat the project
black --check .   # fail in CI if anything isn't formatted

Pylint: a second pair of eyes

Pylint reads your code and reports likely bugs, unused imports, undefined names, overly complex functions and style problems.

pylint mypackage

It’s thorough, which also means noisy at first. Tune it with a config file, and turn off the checks your team doesn’t care about.

pytest: testing that gets out of the way

pytest is the heart of how we work in Python. Tests are plain functions using plain assert, and pytest explains failures clearly.

import pytest
from calc import add


def test_add():
    assert add(2, 2) == 4


@pytest.mark.parametrize("a, b, expected", [(1, 1, 2), (-1, 1, 0), (0, 0, 0)])
def test_add_cases(a, b, expected):
    assert add(a, b) == expected

Fixtures handle setup and teardown, and a large plugin ecosystem adds coverage, parallel runs and more.

What else belongs in the toolbox

The list above covers the web, data, databases and code quality. These are the other modules we see in almost every serious Python project.

In the standard library

Python ships with “batteries included”. Check here before installing anything:

  • pathlib for working with files and paths.
  • json and csv for the most common data formats.
  • datetime and zoneinfo for dates and time zones.
  • logging for proper logs instead of print.
  • argparse for command-line options.
  • dataclasses for simple classes that hold data.
  • collections, itertools and functools for everyday data-structure and iteration tools.
  • subprocess for running other programs.
  • sqlite3 for a real database in a single file.
  • unittest.mock for replacing dependencies in tests.
  • asyncio for concurrent network code.

Third-party favorites

  • NumPy: fast arrays and math. pandas, SciPy and most of scientific Python are built on it.
  • Matplotlib: the standard plotting library.
  • scikit-learn: classic machine learning, with a consistent, approachable API.
  • FastAPI and Flask: lighter web frameworks for APIs and small sites.
  • Pydantic: data validation using type hints. FastAPI is built on it.
  • HTTPX: a Requests-style HTTP client with async and HTTP/2.
  • Beautiful Soup: parsing messy HTML.
  • Click or Typer: friendlier command-line tools than argparse.
  • Rich: color, tables and progress bars in the terminal.
  • PyYAML and python-dotenv: config files and environment variables.
  • Celery: background jobs and task queues.
  • Boto3: the AWS SDK.

Tools around the code

  • uv: a very fast package and project manager that replaces pip, virtualenv and more.
  • mypy: a static type checker that catches type errors before runtime.
  • Ruff: fast linting and formatting, as above.
  • pytest plugins: pytest-cov for coverage and Hypothesis for property-based tests that generate inputs for you.
  • pre-commit: runs formatters, linters and checks on every commit.

Getting started

Start with the standard library, add libraries only when they clearly earn their place, and set up pytest, a formatter and a linter on day one. Python makes it easy to write code quickly. A green test suite keeps it easy to change later.