Python module
Lesson 6
Errors and logging
Catch failures on purpose and log what jobs did — print is not enough.
beginner30 minRun on your machine
What you will be able to do
- Raise and catch exceptions with try/except
- Configure basic logging to the console
- Prefer logging over print in job-style scripts
Why this matters for data work
A silent failure loads half a table. Exceptions stop the job; logging leaves a trail for the next on-call. Schedulers capture stdout/stderr — structured logs beat scattered prints.
Concepts
Exception — error object. raise ValueError("bad row") fails loudly.
try / except — catch only what you can handle. Bare except: hides bugs.
else / finally — optional; finally always runs (close files, etc.).
logging — levels: DEBUG, INFO, WARNING, ERROR. logging.basicConfig once at startup.
Practice on your machine
cd ~/dcubes/python-lab
source .venv/bin/activate
cat > logging_lab.py << 'EOF'
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
)
log = logging.getLogger("lab")
def parse_quantity(raw: str) -> int:
try:
value = int(raw)
except ValueError as exc:
raise ValueError(f"quantity not an int: {raw!r}") from exc
if value <= 0:
raise ValueError(f"quantity must be positive: {value}")
return value
for cell in ["3", "x", "-1"]:
try:
q = parse_quantity(cell)
log.info("parsed quantity=%s", q)
except ValueError as exc:
log.error("skip row: %s", exc)
EOF
python logging_lab.py
You should see one INFO line for 3 and ERROR lines for the bad cells.
What you should see
- Timestamps and levels on each log line.
- Bad inputs do not crash the whole loop when you catch per row (choose crash vs skip deliberately in real jobs).
Common mistakes
except Exception: pass— swallows everything.- Logging secrets (passwords, tokens). Redact.
- print + logging mixed without a convention — pick logging for jobs.