Chapter 4 · Mid-level Developer

The standard library: random, datetime, pathlib

Python comes with a huge standard library — hundreds of modules installed with the language itself. "Batteries included" is the slogan: before reaching for an external package, check whether the stdlib already does it.

You bring a module into your file with import name, then use it as name.thing(). Three you'll reach for constantly:

  • random — controlled randomness. Crucially, random.seed(n) makes it *reproducible*: seed with the same number and you get the same "random" results every run. Vital for tests.
  • datetime — dates and times. Subtracting two dates gives a timedelta, whose .days tells you the gap.
  • pathlib — modern file-path handling. Path("...") wraps a path and gives you .name, .stem, .suffix, .parent — no fragile string-splitting on /.

You don't need to memorise these. Know they exist, know roughly what's in them, and look up the rest.

Syntax

import random, datetime, pathlib

random.seed(42)              # make randomness reproducible
random.choice(["a", "b"])   # pick one item
random.randint(1, 6)         # int between 1 and 6 inclusive

datetime.date.today()        # today's date
(date_a - date_b).days       # gap in whole days

p = pathlib.Path("/logs/errors.log")
p.stem      # "errors"  (name without extension)
p.suffix    # ".log"
p.parent    # PosixPath("/logs")

Worked examples

random — seed it for a repeatable pick

import random

random.seed(42)
print(random.choice(['a', 'b', 'c', 'd']))   # a
random.seed(42)
print(random.choice(['a', 'b', 'c', 'd']))   # a  (same seed → same pick)

random.seed(42)
print(random.randint(1, 6))   # 6  (1..6 inclusive)

datetime — the gap between two dates

import datetime

start = datetime.date(2026, 12, 1)
end = datetime.date(2026, 12, 25)
gap = end - start            # a timedelta
print(gap.days)              # 24
print(type(gap).__name__)    # timedelta

# Days from today until a target date:
def days_until(year, month, day):
    target = datetime.date(year, month, day)
    return (target - datetime.date.today()).days

pathlib — pull a path apart

import pathlib

p = pathlib.Path('/logs/errors.log')
print(p.name)     # errors.log
print(p.stem)     # errors
print(p.suffix)   # .log
print(p.parent)   # /logs

# Build a path with / instead of string-glue:
out = pathlib.Path('/data') / 'report.csv'
print(out)        # /data/report.csv

Common mistakes & gotchas

random is not for security

random is fine for games, shuffles, and test data, but it's predictable — never use it for passwords, tokens or session IDs. For anything security-sensitive use the secrets module instead.

randint is inclusive on both ends

random.randint(1, 6) can return 6 — unlike range(1, 6) which stops at 5. If you want 0..n-1, use random.randrange(n) instead, which matches range's exclusive-stop behaviour.

Don't parse paths by hand

Splitting a path on "/" or "." breaks on edge cases (archive.tar.gz, Windows backslashes, trailing slashes). pathlib.Path handles all of that. Reach for it instead of str.split("/").

Why it matters

The standard library is the difference between writing ten lines and writing ten thousand. Real developers spend a surprising amount of time just knowing which battery is already in the box — random, datetime and pathlib alone cover a huge slice of everyday backend work.