JJoeven

Curriculum/Python

Useful Standard Library

Use datetime, Counter, defaultdict, islice, sha256, uuid, and copy. Know that time.sleep blocks the whole program.

intermediate20 min28 / 37

The standard library is the set of modules that come with Python. You do not need pip for these. They run in Joeven. Look here before you add a package. Agent code leans on a small set: time stamps, counts, copies, ids, and hashes.

You already used json, pathlib, copy, math, and re (next lesson). This page is a map of a few more that show up in traces and tests. It is not a tour of every stdlib module. http.client exists; we still will not hit the network here.

A few stdlib tools
datetimeCountersha256uuid

These modules come with Python. Stamp time, count tools, id a run. Do not sleep for long.

A few stdlib tools

Cheat sheet

ModuleJob
datetimeWhen did this step happen?
collections.CounterHow often did each tool run?
collections.defaultdictGroup rows without a KeyError
itertools.isliceTake the first n items
hashlib.sha256Fingerprint bytes; .hexdigest() is hex text
uuid.uuid4A unique id
copyCopy a list or dict
time.sleepWait. This blocks.
time.timeA clock number you can print

datetime

Store time in UTC. Use .isoformat() when you put a timestamp in a trace. Local time depends on the machine. UTC is comparable.

timedelta is a duration, like five minutes. Add it to a datetime to get a later time. Useful for “this observation is stale.” Do not parse model-written dates with guesswork if you can store ISO strings you created.

datetime.now(timezone.utc) is the current UTC time. Naive datetimes (no timezone) cause bugs when you compare. Prefer timezone-aware.

Counter and defaultdict

Counter counts hashable items. Tool names, error words, status flags. Counter(tools)["search"] is how many times search ran. Counter is a dict subclass. Missing keys look like 0 when you index, which is handy. Still .get if you want.

defaultdict(list) makes a new list when a key is new. You can append without checking if key in d first. defaultdict(int) is a manual counter. Counter is clearer for counts.

Do not defaultdict(list) as a transcript. You would still need an order of keys. Use a list of rows for order, then group with defaultdict when you report.

islice, sha256, uuid, copy

islice(items, n) takes the first n items. Useful when a trace is long and you only want a prefix. For a suffix, slice the list: items[-n:]. islice shines on lazy iterators. On a list, a slice is fine.

hashlib.sha256(data).hexdigest() turns bytes into a hex string. Use it to see if text changed. Pass bytes, like b"hello" or text.encode("utf-8"). Do not hash secrets into a public log if the secret can be guessed. Hash prompts to detect “same prompt as last time,” not passwords.

uuid.uuid4() makes a random unique id. Turn it into text with str(...). Good for a run id. Not good as a security token by itself in every system, but fine as a log correlation id.

copy.copy copies the outer object. Nested dicts are still shared. copy.deepcopy copies nested objects too. You saw this in mutability. It lives in stdlib, so it belongs on the map.

time.sleep blocks

Blocks means the program waits and does nothing else. A long time.sleep(30) freezes that wait. In Joeven it would freeze the page. In an agent loop it would stall every other step.

Mention sleep. Do not sleep for a long time here. If you need a pause on a real server, keep it short and log why. Retries should print “would wait” in this editor. The next agent lesson on retries follows that rule.

Do not call a long time.sleep in a Try it box. The page waits until it finishes.

random.choice is also stdlib and useful for a fake model that picks a canned line. random is not a substitute for tests. urllib exists and still needs a network. Skip it here. argparse builds command-line flags for a laptop main. Skip it here. The table above is the set you will actually type in traces.

When you group with defaultdict(list), convert to dict(grouped) before you JSON-dump if you want a plain object. json.dumps can dump a defaultdict, but tests that compare to a literal dict are easier with a plain dict. Counter dumps as an object of counts. Good for a report row.

Common mistakes

  • Naive datetime vs UTC.
  • Hashing a str without .encode.
  • time.sleep in the agent loop as “backoff” with huge numbers.
  • defaultdict hiding missing-key bugs you needed to see.
  • Using uuid as a substitute for checking allowlists.
Live PythonOpen full playgroundpython
Output
Run to execute this in your browser. Nothing is sent to a server.

Read counts as a policy report: search ran more than read. That report is how you catch a loop that hammers one tool.

How agents use this

Stamp each trace row with UTC time. Count tool names with Counter. Group errors with defaultdict. Take the last few steps with islice (or a slice on a list). Hash a prompt to see if it changed. Give each run a uuid4 id. Copy state before a risky step. Do not sleep for a long time in the loop — that blocks everything else.

A run id in every log line lets you grep one conversation out of a file of many. A hash of the assembled prompt lets you notice “we sent the same 8k characters again.” A Counter in a weekly report lets you see that search is 90% of calls. None of that needs a third-party package.

When you later install httpx on a laptop, you still keep these modules. The stdlib is the floor. Packages are extra. Joeven’s sandbox is that floor on purpose.

Check your understanding

Why is a long time.sleep a problem in an agent loop?