Guide · Python · about 6 minutes

Python cheatsheet: the basics by task

Everything from the Python basics track on one page: what each error means and where to look, values, lists and dictionaries, loops, functions, files, APIs, scripts you can trust, settings and FastAPI. Each row links to the lesson that explains it.

Last checked October 2026

How to use this page

Find the job you're trying to do, and copy the pattern. Words in capitals, like FILE or NAME, are yours to replace. The examples come from the website checker you build across the track. Every row links to the lesson that explains it. Use the print button at the top to keep a copy next to you.

Two habits that make everything here easier:

  • Try it at the >>> prompt first. Run python3, type the one line you're unsure of, and see what it gives back. exit() leaves.
  • Read a traceback from the bottom. The last line names the error; the File ... line just above it says where.

When Python says no

Start here when a script stops. Find the last line of the traceback.

The last line saysIt meansLook atLesson
SyntaxErrorPython couldn't understand the file, so nothing ran at allThe line named, and the one just before it: a missing quote, bracket or colon1
IndentationErrorThe file's shape is wrong. A line ending in : needs indented lines after itThe spaces at the start of the lines around it3
NameError: name 'x' is not definedA name Python hasn't seen: a typo, or a missing importThe spelling, and the imports at the top2, 5
TypeErrorThe wrong type for the job, like comparing text with a number, or a function given too few valuesWhat type each value really is: type(x)2, 4
ValueError: invalid literal for int()The right type, but a value that makes no sense, like int("n/a")The data. Catch it with try and except ValueError4
KeyError: 'status'The dictionary has no key with that name. Keys must match exactlyThe key's spelling, or the file's header line. Use .get() if it might be missing3, 5
IndexError: list index out of rangeA position the list doesn't have. Counting starts at 0len(the_list)3
FileNotFoundErrorNo file at that path, often because the script ran from another folderWhere you ran it from: pwd5
ModuleNotFoundError: No module named 'requests'The package isn't installed for this Python, usually because the virtual environment isn't activesource .venv/bin/activate, then pip install6, 8
error: unrecognized argumentsA misspelled command-line optionpython3 checker.py --help8
Address already in useAnother copy of your API is already running on that portThe other terminal. Stop it with Ctrl+C10

Running Python

ToRunLesson
Check it's installedpython3 --version1
Try things at the prompt (exit() leaves)python31
Run a scriptpython3 checker.py1
Run one linepython3 -c "print(2 + 2)"9
Make a virtual environment (once per project)python3 -m venv .venv6
Switch it on (Mac and Linux)source .venv/bin/activate6
Switch it on (Windows).venv\Scripts\activate6
Install a package into itpip install requests6
Run the testspytest7
See a script's exit codeecho $?7
Start a FastAPI app while you work on itfastapi dev api.py10

Values, types and text

ToWriteLesson
Text, a whole number, a decimal, true or false"example.com", 200, 0.25, True2
Ask what type something istype(200)2
Give a value a namestatus_code = 2002
Divide, whole-number divide, remainder, power7 / 2, 7 // 2, 7 % 2, 2 ** 102
Compare==, !=, <, <=, >, >=2
Combine conditionsand, or, not2
Roundround(0.256 * 1000)2
Join or repeat text"web" + "site", "-" * 102
Capitals"hello".upper()1
Text to a number, and backint("200"), float("0.25"), str(200)2
Nothing at allNone, checked with x is None6

f-strings put values inside text. Anything in braces is worked out, and :.2f means two decimal places:

PYTHON
site = "example.com"
status_code = 200
response_seconds = 0.256
print(f"{site}: {status_code} in {response_seconds:.2f} seconds")

That prints example.com: 200 in 0.26 seconds. Text from the keyboard or a file is always text: "25" * 2 is '2525', so convert first with int().

Lists and dictionaries

A list keeps values in order. A dictionary keeps values with labels, called keys.

ToWriteLesson
Make a listsites = ["example.com", "example.org"]3
First item, last itemsites[0], sites[-1]3
How manylen(sites)3
Add one to the endsites.append("example.net")3
Is it in the list?"example.org" in sites3
Make a dictionarysite = {"name": "example.com", "status_code": 200}3
Read a valuesite["name"]3
Read a value that might be missingsite.get("owner", "unknown")3
Change or add a valuesite["status_code"] = 5033
A list of dictionaries: a table of recordssites = [{"name": "a.com"}, {"name": "b.com"}]3

Decisions and loops

PYTHON
if status_code < 400:
    print("up")
elif status_code < 500:
    print("client error")
else:
    print("down")

for site in sites:
    print(site["name"])

attempts = 0
while attempts < 3:
    attempts = attempts + 1

The colon and the indented lines after it are the rule: everything indented under if, for or while belongs to it. Use four spaces. for goes through every item; while repeats as long as its condition is true, so make sure something changes it. Lesson 3 covers both.

Functions

PYTHON
def to_ms(seconds):
    return round(seconds * 1000)

def fetch(url, max_attempts=3, timeout=5):
    ...

response_ms = to_ms(0.25)
response = fetch("https://github.com", timeout=10)
ToWriteLesson
Make a functiondef name(value):, then indented lines4
Hand an answer backreturn value. Without it, the function gives back None4
A setting with a defaultdef fetch(url, timeout=5):8
Pass a value by namefetch(url, timeout=10)8

Errors you expect: try and except

PYTHON
try:
    status_code = int(site["status_code"])
except ValueError:
    print("status code isn't a number")
    status_code = 0

If the try lines raise that error, Python runs the except lines instead of stopping. Name the exact error you expect, like ValueError or requests.RequestException. A bare except: hides the mistakes you'd want to see. Lessons 4 and 6.

Files: CSV and JSON

PYTHON
import csv
import json

def load_sites(path):
    with open(path, newline="") as file:
        return list(csv.DictReader(file))

def save_results(path, results):
    with open(path, "w") as file:
        json.dump(results, file, indent=2)
  • import loads a module from Python's toolbox, at the top of the file.
  • with open(...) as file: opens a file and closes it again when the indented lines finish, even if something fails.
  • csv.DictReader turns each row into a dictionary, using the header line as the keys. Every value comes back as text.
  • json.dump saves lists and dictionaries as JSON; json.load(file) reads them back. "w" means write, replacing what was there.

Lesson 5 covers both.

Talking to APIs

PYTHON
import requests

response = requests.get("https://github.com", timeout=5)
response.status_code
response.elapsed.total_seconds()
data = response.json()

requests.post("https://ntfy.sh/TOPIC", data="2 sites down", timeout=10)

Always set timeout, or a server that never answers makes your script wait forever. A failed connection raises requests.RequestException; catch it, wait with time.sleep(1), and try again a few times. A 404 is not an exception: it's an answer, so check status_code. Lessons 6 and 9.

Scripts you can trust

PYTHON
import sys

def main():
    ...
    if down > 0:
        return 1
    return 0

if __name__ == "__main__":
    sys.exit(main())
  • main() holds what the script does, so other files and tests can import its functions without running it.
  • The exit code is how cron, CI pipelines and other scripts know it failed: 0 for success, anything else for a problem.
  • Tests live in test_checker.py. Each one is a function whose name starts with test_, using assert:
PYTHON
from checker import is_up

def test_400_is_down():
    assert not is_up(400)

Lesson 7 covers all three.

Arguments, logging and schedules

ToWriteLesson
Take options like --sites work.csvargparse.ArgumentParser(), add_argument("--sites", default="sites.csv"), then parse_args()8
Read an optionargs.sites8
Log to a file and the screenlogging.basicConfig(level=logging.INFO, handlers=[...])8
Log at a levellogging.info(...), logging.warning(...), logging.error(...)8
Edit your scheduleEDITOR=nano crontab -e8
Every 15 minutes, with full paths*/15 * * * * /full/path/.venv/bin/python /full/path/checker.py8
List your schedulecrontab -l8

Cron runs with almost nothing set up: no virtual environment and a different folder. That's why the schedule uses full paths, and the .venv's own python.

Settings and secrets

ToWriteLesson
Set a setting for one runCHECKER_TIMEOUT=10 python3 checker.py9
Set it for this terminalexport CHECKER_TIMEOUT=109
Read it, with a fallbackos.environ.get("CHECKER_TIMEOUT", "5")9
Only if it's setif topic:, since a missing setting is None9
A random, hard-to-guess namepython3 -c "import secrets; print(secrets.token_hex(8))"9

Settings come from the environment, never from the code, so the same script runs anywhere. Secrets especially: a password in the code ends up in Git.

FastAPI

PYTHON
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI(title="Site checker API")

class SiteResult(BaseModel):
    name: str
    result: str

@app.get("/health")
def health():
    return {"status": "ok"}

@app.get("/results/{name}")
def one_result(name: str) -> SiteResult:
    for site in load_results():
        if site["name"] == name:
            return site
    raise HTTPException(status_code=404, detail="Site not found")
  • @app.get("/path") turns the function under it into an endpoint. {name} in the path becomes the function's name.
  • class SiteResult(BaseModel) describes the shape of the data, and FastAPI checks every answer against it.
  • raise HTTPException(...) answers with an error status, like 404 or 503, instead of crashing.
  • /docs on your running API lists every endpoint, and lets you try them.
  • Test it with TestClient(app), then client.get("/health"), in a normal pytest test.

Lesson 10 builds it all.