Python
exception handling
debugging
programming
error logging

How do I print an exception in Python?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Printing an exception in Python can mean different things depending on what you need. Sometimes you only want the error message, and sometimes you need the full traceback so you can see where the failure came from. The right choice depends on whether you are debugging a small script, building a service, or recording production failures.

Core Sections

The simplest form is to catch the exception and print the exception object. That gives you the exception message, but not the full traceback.

python
1try:
2    value = int("not-a-number")
3except ValueError as exc:
4    print(exc)

This is useful when the message itself is enough, such as in a short script or a command-line tool that wants to show a concise error to the user.

The limitation is that it does not tell you where the exception originated unless your code already makes that obvious.

Use traceback.print_exc() for debugging

If you need the stack trace, use the traceback module.

python
1import traceback
2
3try:
4    result = 10 / 0
5except ZeroDivisionError:
6    traceback.print_exc()

This prints the full traceback to standard error, which is usually what you want during debugging. It shows the line where the exception happened and the call path that led there.

That makes it much more useful than print(exc) when the failure is inside a deeper call stack.

Use logging.exception() in application code

For real applications, printing directly to standard output is often not enough. Python’s logging module is usually the better choice because it captures structured messages and can write to files, consoles, or centralized log systems.

python
1import logging
2
3logging.basicConfig(level=logging.ERROR)
4
5try:
6    {}["missing"]
7except KeyError:
8    logging.exception("Failed while reading required key")

logging.exception() is especially convenient because it automatically includes traceback information when called inside an except block.

This is generally the strongest default for web apps, background workers, and long-running services.

Know the difference between user-facing and developer-facing output

A common design mistake is showing raw exception details directly to end users. The traceback is valuable to developers, but it can be noisy, confusing, or even sensitive in user-facing contexts.

A better pattern is:

  • log the full exception internally
  • show a short safe message to the user
python
1import logging
2
3logging.basicConfig(level=logging.ERROR)
4
5try:
6    with open("missing.txt") as fh:
7        print(fh.read())
8except OSError:
9    logging.exception("File operation failed")
10    print("Could not read the file.")

This keeps debugging information available without leaking implementation details to the outside.

Re-raising after printing or logging

Sometimes you want to record the exception and still let it propagate. In that case, log it and then re-raise.

python
1import logging
2
3logging.basicConfig(level=logging.ERROR)
4
5
6def parse_port(text: str) -> int:
7    try:
8        return int(text)
9    except ValueError:
10        logging.exception("Invalid port value: %s", text)
11        raise
12
13
14parse_port("abc")

This pattern is useful when the current layer wants to add context but should not silently swallow the error.

Avoid broad exception handling unless you mean it

It is tempting to write except Exception as exc: everywhere and just print the error. That is acceptable for a top-level entry point, but lower-level code should usually catch specific exceptions.

Catching everything too early can hide programming errors, make recovery logic too broad, and produce logs that are harder to interpret.

Common Pitfalls

  • Using print(exc) when you really need the full traceback leaves out the most useful debugging information.
  • Catching Exception too broadly can hide bugs that should fail fast instead of being silently logged.
  • Printing raw tracebacks directly to end users exposes details that belong in internal logs, not in user interfaces.
  • Logging only a custom message without the exception context makes later debugging much harder.
  • Swallowing the exception after printing it can let the program continue in an invalid state.

Summary

  • 'print(exc) shows only the exception message.'
  • 'traceback.print_exc() shows the full traceback and is better for interactive debugging.'
  • 'logging.exception() is usually the best choice in real applications because it records both message and traceback.'
  • Separate user-facing error messages from developer-facing diagnostic details.
  • If the exception should still fail the operation, log it and then re-raise it.

Course illustration
Course illustration

All Rights Reserved.