Faragiri

Learn Python Languages · Python basics, The standard library, Packages and environments and 2 more

Eleven lines of standard library that total a garden water meter, and then the second week, which is not about Python at all.

5Branches
5Nodes below
3Depth

Already installed

The four modules Ramin's script is made of

These are one surface rather than four libraries: shipped together, versioned together, and written to be handed to each other.

The standard library
  • pathlibA path that can open, join, glob and check itself
  • csvDictReader, keyed by the header line
  • collectionsdefaultdict, so a missing key is not a guard
  • statisticsmedian, mean, and the honest float when there are two values
  • jsonThe same rows, on the way out to something else
  • sqlite3A real database, in the interpreter, with no server
  • pathlibA path that can open, join, glob and check itself
  • csvDictReader, keyed by the header line
  • collectionsdefaultdict, so a missing key is not a guard
  • statisticsmedian, mean, and the honest float when there are two values
  • jsonThe same rows, on the way out to something else
  • sqlite3A real database, in the interpreter, with no server

Six of about two hundred. The figure does not say which are good, only that reaching outside for any of them starts a second problem.

Ramin logs the water meter at a community garden in Kerman into a spreadsheet, and wants a total per plot. Eleven lines, nothing installed, and it prints:

  • A: 431 litres over 3 readings, median 142
  • B: 194 litres over 2 readings, median 97.0

The whole of it is four imports and a loop. csv.DictReader gives you a dict per row, keyed by the header line, so r["litres"] works without counting columns. Path("meter.csv").open() replaces open() with a path built by hand, and it is the one to learn because the same object joins, globs and checks existence. defaultdict(list) appends to a key that does not exist yet, which removes the two line guard everybody writes first. And f"{plot}: {sum(litres)} litres" evaluates the expression inside the braces, arithmetic included.

One line is doing quiet work: if r["litres"] skips the empty string a missing reading leaves behind, because a blank cell arrives from CSV as "" and never as None. Miss it and int("") stops the program, which is the commonest first crash in a script like this.

The output has a detail worth noticing. statistics.median of two values returns their mean, so the type becomes a float, which is why plot B prints 97.0 and plot A prints 142. Nothing is wrong; the function is telling you how many readings it had.

The library is the language, in practice

Nothing above came from a package. csv, pathlib, statistics and collections ship with the interpreter, they are versioned with it, and they are written to be used together, which is what makes reaching for a dependency the second move rather than the first. Dates, JSON, HTTP requests, zip files, SQLite and a test runner are all in there on the same terms. Knowing what is already present is the difference between an eleven line script and a project with a dependency file, and it is what ships with Python, and saves you a dependency.

The syntax underneath it is genuinely small: indentation carries the blocks, there are no braces and no semicolons, and a beginner reads a page of it before being taught any of it. That readability is the reason it is handed out first, and it is covered as syntax, types and the standard idioms. It is also the reason people underestimate what is left.

What is left is the environment, and it is most of the fortnight

Ramin's script runs. Ramin's script runs on Ramin's laptop. The gap between those two sentences is where the second week goes, and none of it is Python.

python3 -m venv .venv makes a project its own interpreter and packages, which is the single move that stops one project's upgrade breaking another. Without it every install is global and every project is competing for the same versions. A lockfile records the exact versions, and it belongs in the repository, because a list of names without versions reproduces whatever is newest on the day somebody clones it rather than what you had.

One more line belongs in any file that might be imported: if __name__ == "__main__" guards code that must not run on import. A file without it does its work when something imports it, and the failure is bewildering, because the import might be the test runner or a process pool starting a worker. Environments, installs and the tools around them are pip, venv, and keeping projects apart.

The second week

What has to hold before the script runs on another machine

Every link carries the whole load, and the one that breaks is never the one anybody studied.

The open link is where a beginner's project actually fails, and it is the only one that costs nothing to fix before it fails.

What to run in 2026

Python 3.14 is the current release. uv, from 2024, is the tool to install first: it is free and open source and it replaced pip, virtualenv and pyenv, three tools that had been doing one job between them. It installs the interpreter version a project asks for and writes the lockfile, which is the paragraph above solved rather than explained.

Ruff is the formatter and linter, also free, also from the same makers, and it replaced flake8, isort and black. Both are one binary and neither needs a Python of its own to run, which is the circular problem that made the old tools painful to explain.

The mistake: reaching for a package before opening the library

The place people stall on this language is not the syntax and it is not the environment either, exactly. It is that the environment problems mostly arrive as a consequence of a dependency, and the dependency was usually not needed. A script that reads a spreadsheet, adds numbers and prints a summary is eleven lines of standard library; the version of it that starts with a data frame library pulls in a compiled dependency, a version constraint and a reason to care about which interpreter is on the path.

The rule that costs nothing: before installing anything, search the standard library for it once. The answer is no often enough to keep the habit honest, and yes often enough to save the fortnight. Ramin's original attempt began with a spreadsheet package and a failed install, and the eleven lines above were what was left after the second attempt.

The unanswered question is what Python is for once the script has to answer to somebody else, and it splits two ways: the same standard library aimed at the boring jobs, in files, spreadsheets and the boring jobs, or a request arriving from outside, in Django, Flask, and serving a request. Which language to spend the fortnight on in the first place is settled in what the choice actually depends on, and what it does not, and the interpreter that runs all of this is what happens between your file and the processor.

Inside this, 5

Above this