Catching all exceptions in Python
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Python makes it easy to catch errors broadly, but broad exception handling is only safe when you define the boundary carefully. In most real applications, the goal is not to swallow everything. The goal is to log failures, release resources, and either recover in a controlled way or stop with a clear error path.
Catch Exception, Not Everything
When developers say "catch all exceptions," they usually mean "catch all ordinary runtime failures." In Python, that usually maps to Exception, not a bare except: block.
Exception covers most failures you expect in application code, including ValueError, TypeError, OSError, and many library exceptions. A bare except: also catches KeyboardInterrupt, SystemExit, and GeneratorExit, which are often supposed to escape so the program can stop cleanly.
This is broad, but it is still reasonable because the function returns a clear fallback and does not hide process-level signals.
Use Broad Catches at Application Boundaries
The best place for a broad except Exception block is near the edge of your program. That might be the entry point for a CLI tool, a background worker loop, or a task runner that needs to keep processing independent jobs.
Here the broad catch is deliberate. One bad job does not kill the whole worker, and the log keeps the original stack trace.
Put Specific Exceptions First
If you know how to recover from a particular failure, catch that exception before the general fallback. This keeps recovery logic explicit and avoids turning every problem into the same generic branch.
This pattern communicates intent. Missing files get a default, permission problems become domain-specific errors, and everything else still fails loudly.
Use finally for Cleanup
Broad exception handling often exists because work must be cleaned up even when something breaks. That is what finally is for. Cleanup belongs there instead of being repeated in multiple except branches.
If the write fails, the file still closes. The exception is logged and then re-raised so the caller can decide whether the program should continue.
Avoid Silent Failure
The most dangerous pattern is catching broadly and doing nothing. That hides bugs, removes stack traces, and produces systems that appear to work while corrupting state or skipping work.
Bad pattern:
If the code really can continue, log the failure and return a documented fallback. If it cannot continue, re-raise after logging.
When BaseException Is Appropriate
Catching BaseException is rare, but it is not always wrong. Some frameworks or cleanup routines use it when they must intercept every exit path temporarily before re-raising. That is a narrow, deliberate use case. In ordinary business logic, it is too broad.
This form only makes sense when you immediately re-raise and truly want to include interrupts and exit signals in the same cleanup path.
Common Pitfalls
- Using a bare
except:whenexcept Exception:is the safer intent. - Swallowing exceptions without logging, returning, or re-raising.
- Catching broad exceptions deep inside library code where callers lose useful context.
- Forgetting to put targeted exception handlers before the general fallback.
- Logging an error message but discarding the original stack trace.
Summary
- In normal Python code, broad handling usually means
except Exception:, not bareexcept:. - Broad catches belong at application boundaries where you can log and recover safely.
- Put specific exception handlers before the general handler.
- Use
finallyfor cleanup and re-raise when the caller still needs to know about the failure. - Avoid silent failure paths that hide bugs and make behavior unpredictable.

