Filters
How to search
  • Plain words find names, texts and examples.
  • "two words" finds the exact phrase.
  • --name or -x finds an option.
  • #word looks only inside commands.
  • @grep finds lessons and labs that use grep.
  • Filters: cat:network · in:labs · in:notes · level:rhcsa · ch:8 · root:yes. Put ! before a word to leave it out. OR between words means one of them.
  • ↑ ↓ to move · Enter to open · Esc to close · / to search

Chapter 8Name in the course: Exceptions and logging

Handle errors and write logs

Scripts that run at night must not crash silently. Catch the errors you expect, let the unexpected ones show clearly, and write logs with time stamps and levels instead of print.

  • 5 Lessons
  • 1 Commands

$ run as a normal user# run as root (or with sudo)

8.1

Catch exceptions

try runs code; except handles a specific error; else runs when there was none; finally always runs.

exceptions.py
import json
 
 
def load_config(path: str) -> dict:
    try:
        with open(path, encoding="utf-8") as f:
            return json.load(f)
    except FileNotFoundError:
        print(f"{path} not found, using defaults")
        return {}
    except json.JSONDecodeError as e:
        raise SystemExit(f"{path} is not valid JSON: line {e.lineno}") from e
    finally:
        print("config step done")

Watch out

Never write a bare except: or except Exception: pass — it hides real bugs. Catch only what you can handle.

8.2

Raise your own errors

Stop early with a clear message when input is wrong.

raise.py
def set_replicas(n: int) -> None:
    if not 1 <= n <= 20:
        raise ValueError(f"replicas must be 1-20, got {n}")
    print("ok", n)

8.3

Write logs with logging

The logging module adds time, level and source, and can write to a file and the screen at once.

log_setup.py
import logging
 
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s %(levelname)-8s %(name)s: %(message)s",
    handlers=[logging.FileHandler("/var/log/backup.log"), logging.StreamHandler()],
)
log = logging.getLogger("backup")
 
log.info("backup started")
log.warning("disk above %d%%", 80)
try:
    1 / 0
except ZeroDivisionError:
    log.exception("calculation failed")
LevelUse
DEBUGDetails for finding bugs
INFONormal steps
WARNINGSomething unusual, still working
ERRORA step failed
CRITICALThe script can not go on

Remember

log.exception(...) inside except also writes the full traceback.

8.4

Log to the journal

Scripts run by systemd can simply log to stdout/stderr — the journal stores it. Or send to syslog.

syslog_log.py
import logging
import logging.handlers
 
log = logging.getLogger("diskcheck")
log.setLevel(logging.INFO)
log.addHandler(logging.handlers.SysLogHandler(address="/dev/log"))
log.info("diskcheck: / is at 71%")
journalctl -t python3 -n 5
journalctl -u diskcheck.service -n 20

8.5

Rotate log files

A long-running script rotates its own log, or leaves it to logrotate.

rotate.py
import logging
from logging.handlers import RotatingFileHandler
 
h = RotatingFileHandler("/var/log/app/app.log", maxBytes=5_000_000, backupCount=5)
logging.getLogger().addHandler(h)

All commands in this chapter