Programming with AI
ENRU
6.6

AI mistakes in Python, and a checklist

how this stack differs from the others

What it is

The chapter's closer: what the AI confuses specifically in Python and how to check Python code in a few minutes.

The general red flags are in article 2.14 and apply here too. This article holds only what is specific to the language.

What to look for

1. Code for an older version of the language

Optional[str] and List[str] instead of str | None and list[str], os.path instead of pathlib, %-formatting instead of f-strings. It will work and it will look dated. Worse is the other way round: modern syntax on an old Python — then it fails at import.

2. Synchronous inside asynchronous

requests instead of aiohttp, sqlite3 instead of aiosqlite, time.sleep instead of asyncio.sleep. The most common mistake in bot code: it works, but the bot stops answering anyone for the duration of every request (articles 2.10, 6.4).

3. gather without return_exceptions

Covered in article 6.4. Visible at a glance and breaks on the first failure of an external service.

4. A mutable default value

def add_item(item, cart=[]):

The list is created once for the lifetime of the program (article 2.5). The AI reproduces this regularly, because there is a lot of it in the training data.

5. Swallowed exceptions

except Exception: pass, .get(key, {}) instead of a check, return None where an error is needed. Covered in articles 2.8 and 2.14 — in Python it is the most common of all, thanks to the convenience of .get().

6. Invented function parameters

The quietest kind of hallucination (article 4.8): a non-existent keyword argument is sometimes simply ignored. Checked with one command:

python3 -c "import inspect, aiohttp; print(inspect.signature(aiohttp.ClientSession.get))"

7. Code outside functions

It runs on import — a database connection, a file read, an API request at module top level (article 2.2). In Python this is especially treacherous, because a module is imported once and the error does not show up immediately.

8. print instead of logging

Acceptable in a script, not in a bot or a service: the output disappears along with the terminal (article 4.2).

What to tell the AI

A check in one prompt:

Prompt
Check your code against this Python-specific list:
- syntax for Python 3.12, nothing older
- no synchronous calls inside async (requests, time.sleep, sqlite3)
- gather, if present, with return_exceptions=True
- no mutable default values in arguments
- no except Exception: pass and no .get() instead of a check
- no code outside functions at top level
- logging via logging, not print

Which of these are present? If none, say so.

A checklist for Python code

Six steps, about three minutes. The order is by return on effort.

1. Does it run

python3 -m weatherbot

Catches invented imports, typos, syntax for the wrong version.

2. Does the type check pass

python3 -m mypy --strict weatherbot/

Catches forgotten None checks, mixed-up types, non-existent methods (article 6.3). The highest-value of the six.

3. Do the tests pass

pytest -q

4. The diff

git diff --stat && git diff

Size, removed lines, boundaries (article 4.7).

5. Asynchrony

By eye: any synchronous calls in an async def, are there timeouts, does gather have return_exceptions.

6. The unhappy case

Run it on empty data or with the network unavailable.

Cheat sheet

  • Specific to Python: old syntax, synchronous inside async, unguarded gather.

  • =[] in arguments and .get() instead of a check are most common here.

  • Check invented keyword arguments with inspect.signature.

  • Checklist: run · mypy --strict · tests · diff · asynchrony · unhappy case.

  • The type check is the highest-value of the six steps.

  • Combine the first three into one command.