How to print an exception in Python 3?

Question:

Right now, I catch the exception in the except Exception: clause, and do print(exception). The result provides no information since it always prints <class 'Exception'>. I knew this used to work in python 2, but how do I do it in python3?

Asked By: Haonan Chen

||

Answers:

Try

try:
    print(undefined_var)
except Exception as e:
    print(e)

this will print the representation given by e.__str__():

"name ‘undefined_var’ is not defined"

you can also use:

print(repr(e))

which will include the Exception class name:

"NameError("name ‘undefined_var’ is not defined",)"

Answered By: wpercy

I’m guessing that you need to assign the Exception to a variable. As shown in the Python 3 tutorial:

def fails():
    x = 1 / 0

try:
    fails()
except Exception as ex:
    print(ex)

To give a brief explanation, as is a pseudo-assignment keyword used in certain compound statements to assign or alias the preceding statement to a variable.

In this case, as assigns the caught exception to a variable allowing for information about the exception to stored and used later, instead of needing to be dealt with immediately.

(This is discussed in detail in the Python 3 Language Reference: The try Statement.)


There are other compound statements that use as. The first is the with statement:

@contextmanager
def opening(filename):
    f = open(filename)
    try:
        yield f
    finally:
        f.close()

with opening(filename) as f:
    # ...read data from f...

Here, with statements are used to wrap the execution of a block with methods defined by context managers. This functions like an extended try...except...finally statement in a neat generator package, and the as statement assigns the generator-produced result from the context manager to a variable for extended use.

(This is discussed in detail in the Python 3 Language Reference: The with Statement.)


As of Python 3.10, match statements also use as:

from random import randint

match randint(0, 2):
    case 0|1 as low:
        print(f"{low} is a low number")
    case _:
        print("not a low number")

match statements take an expression (in this case, randint(0, 2)) and compare its value to each case branch one at a time until one of them succeeds, at which point it executes that branch’s block. In a case branch, as can be used to assign the value of the branch to a variable if that branch succeeds. If it doesn’t succeed, it is not bound.

(The match statement is covered by the tutorial and discussed in detail in the Python 3 Language Reference: match Statements.)


Finally, as can be used when importing modules, to alias a module to a different (usually shorter) name:

import foo.bar.baz as fbb

This is discussed in detail in the Python 3 Language Reference: The import Statement.

Answered By: Noah Bogart

These are the changes since python 2:

    try:
        1 / 0
    except Exception as e: # (as opposed to except Exception, e:)
                           # ^ that will just look for two classes, Exception and e
        # for the repr
        print(repr(e))
        # for just the message, or str(e), since print calls str under the hood
        print(e)
        # the arguments that the exception has been called with. 
        # the first one is usually the message. (OSError is different, though)
        print(e.args)

You can look into the standard library module traceback for fancier stuff.

Answered By: rigel

I’ve use this :

except (socket.timeout, KeyboardInterrupt) as e:
    logging.debug("Exception : {}".format(str(e.__str__).split(" ")[3]))
    break

Let me know if it does not work for you !!

Answered By: Nicolas Huynh

Here is the way I like that prints out all of the error stack.

import logging

try:
    1 / 0
except Exception as _e:
    # any one of the follows:
    # print(logging.traceback.format_exc())
    logging.error(logging.traceback.format_exc())

The output looks as the follows:

ERROR:root:Traceback (most recent call last):
  File "/PATH-TO-YOUR/filename.py", line 4, in <module>
    1 / 0
ZeroDivisionError: division by zero

LOGGING_FORMAT :

LOGGING_FORMAT = '%(asctime)sn  File "%(pathname)s", line %(lineno)dn  %(levelname)s [%(message)s]'
Answered By: caot

Although if you want a code that is compatible with both python2 and python3 you can use this:

import logging
try:
    1/0
except Exception as e:
    if hasattr(e, 'message'):
        logging.warning('python2')
        logging.error(e.message)
    else:
        logging.warning('python3')
        logging.error(e)

[In Python3]

Let’s say you want to handle an IndexError and print the traceback, you can do the following:

from traceback import print_tb 
empty_list = [] 
try: 
    x = empty_list[100]
except IndexError as index_error: 
    print_tb(index_error.__traceback__)

Note: You can use the format_tb function instead of print_tb to get the traceback as a string for logging purposes.
Hope this helps.

Answered By: RaviTezu

Don’t use print(e), since that won’t print a stack trace, which is a nightmare for debugging. traceback.print_exception is what you’re looking for:

import traceback
try:
    assert False
except Exception as e:
    traceback.print_exception(e)
Answered By: Glenn Maynard

You can do:

with self.assertRaisesMessage(ValueError, 'invalid literal for int()'):
  int('a')

Reference

Answered By: Abhinaya