The twenty-fourth lesson of the Python course. The pandas module opens with the question it ought to open with: is the library worth it. A measurement answers, not belief. Where pandas is forty times faster, where it is merely twice, where it loses to an ordinary loop, what the memory costs — and the rule for when a table is needed.
The twenty-third lesson of the Python course. A program that works through the night without you: arguments instead of editing the source, a journal with levels instead of `print`, a lock against two runs at once, and the exit code — the one thing the scheduler actually reads. Plus cron, launchd and systemd.
The twenty-second lesson of the Python course. The database does the counting: `GROUP BY` gives one row per currency, `JOIN` brings the names from a second table, and a month is a group made of the first seven characters of the date. Plus the trap: over an empty answer `avg` returns `None` rather than zero.
The twenty-first lesson of the Python course. A database instead of a file: a row is added, yesterday's stay, and running the same day again makes no duplicates. Plus two measured traps: a value glued into a query returned the whole table instead of one currency, and closing without a `commit` lost the row.
The twentieth lesson of the Python course. Politeness to somebody else's server is three concrete things: a timeout, so you do not wait for ever; a retry with the pause doubling, so you do not hit what is already down; and a cache, so you do not ask twice. Measured on a server of our own: four readings, one request.
The nineteenth lesson of the Python course. The same answer from the National Bank, read by a parser this time: 39 currencies, the rate taken by the name of a tag rather than by cutting a string. Plus two traps: `find` returns `None` for a tag that is not there, and a tag in a namespace is not found by its short name at all.
The eighteenth lesson of the Python course. A request to the National Bank: 200, `text/xml`, 11,407 bytes — and those are `bytes`, not a string. Plus the difference that breaks error handling: `HTTPError` means the server said no, `URLError` means there was no answer at all.
The seventeenth lesson of the Python course. The digest has grown into one long file, and it is time to lay it out under names. `import` runs somebody else's file whole, `__name__` tells a module from the file that was started, and your own `csv.py` beside the program quietly replaces the standard one.
The sixteenth lesson of the Python course. A hundred thousand squares take almost four megabytes as a list and 376 bytes as a generator — measured, with every number counted in. The difference is not in how you count them but in when the values appear. Plus the mistake that matters: a generator is good for one pass, and the second one quietly gives you nothing.
The fifteenth lesson of the Python course. Of the five names in the list only four are different: a set swallows the repeat without a word. In exchange, three questions about two exports take three signs: `&` for what is in both, `-` for what is gone, `|` for all of it. Plus `{}` is an empty dictionary, not an empty set.
The fourteenth lesson of the Python course. There are 45 days between the 15th of January and the 1st of March, and `timedelta` counts them, not you. Plus two traps: `01.02.2026` parses under two formats without an error — as January and as February — and a naive time cannot be taken from an aware one, which Python says outright.