Exceptions, Logging and Testing
Know exactly how try/except/else/finally behave, how exceptions chain and group, how logging decides what to emit, and how pytest and unittest.mock work so tests catch real bugs instead of hiding them.
Key points
- 1
except Exceptionmisses BaseException subclasses (KeyboardInterrupt, SystemExit, GeneratorExit); a bareexcept:catches them all, which can swallow sys.exit() and Ctrl+C. - 2
finallyalways runs. Areturnor exception inside it replaces the pending result or exception, so keep cleanup code simple and never return from it. - 3
raise X from esets __cause__ ("direct cause"), implicit raising sets __context__ ("During handling…"), andfrom Nonehides the context while still storing it. - 4
except*(3.11+) can run several clauses for one ExceptionGroup, always binds a group, re-raises unmatched leaves as a new group, and forbids return/break/continue inside the block. - 5
Logging: records pass the logger level, then each handler level, then propagate to ancestor handlers. basicConfig is ignored once handlers exist unless force=True. Use lazy %-style arguments.
- 6
pytest: fixtures with yield give setup/teardown, scopes control lifetime, parametrize multiplies, raises(match=) is a regex search, and approx compares floats.
- 7
unittest.mock: patch where the name is looked up, prefer spec/autospec, and remember side_effect beats return_value and raises StopIteration when an iterable runs out.
Common traps
The name bound by
except ... as eis deleted when the block ends, even ifeexisted before.assertstatements disappear underpython -O, so never use them for validation.Patching
module.attrdoes nothing for code that already didfrom module import attr; patch the importing module instead.
Test yourself on Exceptions, Logging and Testing
Ten questions, with the answer and explanation after each one.