Python Part I · Module 13 · Modules, Packages and Imports
The Standard Library
Several hundred modules ship with every Python installation, covering mathematics, dates, structured data, file paths, compression, networking and a great deal more. Nobody memorises them, and this chapter does not ask you to. What is worth building instead is a habit: before writing forty lines to parse a date or tally a list or join a path, spend thirty seconds checking whether it is already there. It usually is, and the version that ships has been tested by more people than will ever read your script. The tour below is the handful an automation engineer reaches for most, chosen so that every example is one you could use this week.
Foundation17 min readPythonPart IFundamentalsModulesStandard Library
Part I · Module 13 · Chapter 13.4 · The Standard Library
1. What "Standard" Means
Three different things can sit behind an import:
- Built in —
print,len,sorted. No import at all. - The standard library — ships with Python, import required, nothing to install.
math,json,pathliband several hundred more. - Third party — written by someone else, installed separately. Not covered in Part I.
The middle one is the subject here, and the practical consequence of "ships with Python" is that it is already on every machine your script will run on. No installation step, no version negotiation with whoever maintains the build servers. For a script that has to run on a licence server you do not administer, that matters.
2. The Habit
The skill is not knowing what is in there. It is asking.
The middle step is the one that gets skipped, and the cost is not only the forty lines. It is that your forty lines have not been tested against leap years, or empty input, or a path containing a space.
3. Numbers: math and statistics
import math
import statistics
runtimes = [120, 450, 90, 300]
print(math.ceil(2.1), math.floor(2.9))
print(round(math.sqrt(2), 4))
print(statistics.mean(runtimes))
print(statistics.median(runtimes))
print(round(statistics.stdev(runtimes), 2))3 2
1.4142
240
210.0
167.93statistics is the one people most often reinvent. A mean is easy to write and a median is easy to write wrongly — the even-length case needs the average of the middle two, which the version above handles without being asked.
Notice the median came back as 210.0 rather than 210. The four runtimes sort to 90, 120, 300, 450, so the median is the average of the middle two — (120 + 300) / 2 — and division always produces a float. A hand-written median that returns an int for even-length input has already got that wrong.
4. Counting: collections.Counter
Chapter 10.10 built a severity tally by hand with a dictionary and .get(). That pattern is common enough to ship:
from collections import Counter
severities = ["error", "info", "error", "fatal", "info", "error"]
counts = Counter(severities)
print(counts)
print(counts["error"])
print(counts.most_common(2))
print(sorted(counts))Counter({'error': 3, 'info': 2, 'fatal': 1})
3
[('error', 3), ('info', 2)]
['error', 'fatal', 'info']A Counter behaves as a dictionary — index it, sort its keys, loop it — with .most_common() added. Chapter 10.10's hand-built version is still worth knowing, because it is the pattern underneath; this is the tested one to reach for.
5. Randomness, and Why You Must Seed It
random is where this audience has a specific requirement most do not:
import random
random.seed(7)
print(random.randint(1, 100))
print(random.choice(["vcs", "xrun", "questa"]))
print(random.sample([4210, 4211, 4212, 4213], 2))42
vcs
[4213, 4212]Run that file again and you get the same three answers. That is the point.
Without random.seed(...), every run produces different values — which for a regression means a failure you cannot reproduce. The seed turns random into arbitrary but repeatable, and reporting it alongside a failure is what lets somebody else run the identical sequence tomorrow.
6. Dates and Times: datetime
from datetime import datetime, timedelta
started = datetime(2026, 10, 7, 14, 30, 0)
finished = started + timedelta(hours=2, minutes=45)
print(started.strftime("%Y-%m-%d %H:%M"))
print(finished.strftime("%H:%M"))
print((finished - started).total_seconds())
print(started.strftime("%d %b %Y"))2026-10-07 14:30
17:15
9900.0
07 Oct 2026Subtracting two datetimes gives a timedelta, and .total_seconds() turns it into a number you can compare against a runtime budget. Adding hours across midnight, across month ends and across leap years all work without you thinking about it — which is the forty lines from Section 2 that you did not write.
datetime.now() gives the current time. It is deliberately not used in this chapter's examples, because its output changes every run and every example here is one you can check.
7. Paths and Rows: pathlib and csv
from pathlib import Path
log = Path("logs") / "axi_smoke" / "run.log"
print(log)
print(log.name)
print(log.suffix)
print(log.stem)
print(log.parent)logs/axi_smoke/run.log
run.log
.log
run
logs/axi_smokeThe / operator joins path segments, and pathlib inserts whatever separator the running system uses — a forward slash on macOS and Linux, a backslash on Windows. A script that builds paths by string concatenation works on one and breaks on the other; this one does not.
csv reads comma-separated rows, and it accepts any sequence of lines — a file once you reach Module 15, or a list right now:
import csv
rows = [
"test,seed,status",
"axi_smoke,4210,PASS",
"axi_burst,4211,FAIL",
]
reader = csv.DictReader(rows)
for row in reader:
print(row["test"], row["seed"], row["status"])axi_smoke 4210 PASS
axi_burst 4211 FAILDictReader uses the first line as field names and hands back a dictionary per row — which is Chapter 8.1's shape, arriving for free. Writing a CSV parser by hand looks easy until a field contains a comma inside quotes, at which point the shipped one is worth a great deal.
8. os and sys: Named, Not Printed
Two more modules belong on any list, and this chapter shows no output from either:
sys— the running interpreter.sys.argv(the command-line arguments),sys.exit(code)(stop with a status),sys.version.os— the operating system. Environment variables, process information, directory operations.
Everything useful in them is specific to the machine and the moment: your Python version, your directory, your environment. Printing any of it here would produce output that does not match what you see, which is exactly the standard this course holds its examples to.
They matter enormously for real automation — reading $PROJECT_ROOT, exiting with a non-zero status so a nightly job notices — and Part II covers them where the surrounding machinery makes them meaningful.
9. The Working Set
| Module | For | Reach for it when |
|---|---|---|
math | arithmetic beyond the operators | ceilings, logs, trigonometry |
statistics | mean, median, stdev | summarising runtimes or coverage |
collections | Counter and friends | tallying anything |
random | choices and sampling | seed sweeps, picking a subset |
datetime | dates, times, durations | timestamps, elapsed time, budgets |
pathlib | file paths as objects | building or inspecting any path |
csv | comma-separated rows | results tables, tool reports |
json | structured text | config, machine-readable results |
sys | the interpreter | arguments, exit status |
os | the system | environment, directories |
Ten modules, all shipped, all available on every machine. That is not the whole library — it is the part a regression script usually needs.
10. Predict, Run, Observe
import math
import random
from collections import Counter
from datetime import datetime, timedelta
random.seed(1)
# A
print("A:", math.ceil(4.01), math.floor(4.99))
# B
print("B:", Counter("axi_axi")["a"])
# C
print("C:", random.randint(1, 10), random.randint(1, 10))
# D
d = datetime(2026, 1, 31) + timedelta(days=1)
print("D:", d.strftime("%d %b"))The verified output:
A: 5 4
B: 2
C: 3 10
D: 01 FebA — ceil always rounds up, floor always down, however close to the boundary.
B — Counter on a string counts characters, and "a" appears twice.
C — seeded, so these two numbers are the same on every run. Remove the seed and they are not.
D — January has 31 days and timedelta knows it. That is the leap-year argument in miniature.
11. Exercises
Exercise 1 — look it up first. For each, name the standard-library module you would check before writing it yourself: (a) the median of a list (b) the number of days between two dates (c) tallying how many times each severity appears (d) joining a directory and a filename (e) reading a comma-separated results table.
Exercise 2 — median by hand, then not. Write a median function for an even-length list, then compare it against statistics.median. Say what your version had to get right.
Exercise 3 — the seed. Print three random integers twice in one file with no seed, then again with random.seed(99) before each group. Explain the difference in two sentences.
Exercise 4 — reproduce a failure. A nightly run reports that axi_burst failed at seed 4211. Write the three lines that would re-run the identical random sequence, and say what would be impossible without the recorded seed.
Exercise 5 — durations. Given a start of 23:30 and a runtime of 95 minutes, print the finish time and the elapsed seconds. Confirm it crosses midnight correctly.
Exercise 6 — path parts. Build the path reports/2026/axi_smoke.json and print its name, stem, suffix and parent. Then say why you did not use string concatenation.
Exercise 7 — a results table. Parse four CSV lines with DictReader and print only the failing rows. Say what DictReader gave you that .split(",") would not.
Exercise 8 — why not os. Explain in two sentences why this chapter names os and sys but prints nothing from them, and what that tells you about writing examples.
12. Summary
- Three sources of code: built in, the standard library, third party. The middle one ships with Python and needs no installation.
- "Already on every machine" is the practical benefit for scripts running where you do not control the build.
- The habit is worth more than the list: check before writing, because the shipped version is tested against the cases you will not think of.
statisticsis the most reinvented — a median is easy to write wrongly.Counteris Chapter 10.10's tally, shipped, and behaves as a dictionary.- Seed
randomdeliberately and record the seed. An unseeded regression failure cannot be reproduced. datetimearithmetic handles month ends and leap years so you do not.pathlibuses the right separator for the running system; string concatenation does not.csv.DictReaderaccepts any sequence of lines and returns a dictionary per row.osandsysare machine-specific, which is why nothing here prints from them.
The next chapter imports something you wrote yourself.
Where this fits
Part of the Python curriculum.
