Catch and print full Python exception traceback without halting/exiting the program
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Sometimes you want the full Python traceback for debugging, but you do not want one bad item to terminate the entire program. The safe pattern is to catch the exception at a task boundary, record the traceback, and continue with the next independent unit of work. The important part is not just how to print the traceback, but where it is correct to recover and keep going.
Print the Current Traceback with traceback.print_exc()
Inside an except block, traceback.print_exc() prints the full stack trace for the current exception:
This is a good fit for batch-style loops where each item is independent. One failed item is reported clearly, and the rest of the work still proceeds.
Capture the Traceback as a String
If you need to store, email, or log the traceback elsewhere, use traceback.format_exc():
This returns the same traceback content as a string, which is often more flexible than printing directly.
Prefer Logging in Real Applications
For scripts, printing may be enough. For applications, workers, and services, use the logging module so the traceback goes through the normal log pipeline.
logging.exception() is especially convenient because it automatically includes the traceback of the current exception when called inside except.
Continue Only at a Safe Boundary
Printing a traceback is easy. Continuing safely is the harder design question.
It is usually reasonable to continue after failures in cases such as:
- one file per iteration in a batch job
- one message per iteration in a queue worker
- one input row per iteration in a data import
It is usually dangerous to continue when the failed code may have left shared state half-updated. If a function partially modifies a transaction, a cache, or a file on disk, blindly continuing can create a harder-to-debug corruption problem.
A safer shape is to isolate one job at a time:
Each job is separate, so recovery is sensible.
What Not to Catch
Avoid catching BaseException just to keep the process alive. That also catches signals such as KeyboardInterrupt and termination paths such as SystemExit, which many programs should allow to behave normally.
In most ordinary application code, except Exception: is the broadest catch you should consider, and even then it belongs at a clear recovery boundary rather than around the whole program.
Re-Raise When Recovery Is Not Real
If the program cannot continue safely, print or log the traceback and then re-raise:
This preserves observability without pretending the failure was harmless.
Common Pitfalls
One common mistake is printing only str(error). That gives you the message but loses the call stack, which is usually the most useful part of the failure report.
Another mistake is catching too much at too low a level. A broad catch buried deep in the call stack can hide programming errors and make the system limp forward in a broken state.
Developers also sometimes catch BaseException to keep the program alive. That interferes with normal interruption and shutdown behavior.
Finally, "continue after error" is not automatically safe. Make sure the failed operation did not leave transactions, files, or shared objects in an inconsistent state before deciding to continue.
Summary
- Use
traceback.print_exc()to print the current exception with its full traceback. - Use
traceback.format_exc()when you need the traceback as a string. - Prefer
logging.exception()in real applications so the traceback is recorded through your logging pipeline. - Catch exceptions around independent tasks, not around the entire program without a recovery plan.
- Continue only when the failed operation cannot corrupt the rest of the run.

