Python exception get function name

How to get the name of an exception that was caught in Python?

For example, I am catching multiple (or all) exceptions, and want to print the name of the exception in an error message.

Why do you think you need this? Why not catch a more concrete exception (e.g. except NameError: ) to begin with?

I have a couple scenarios where I want to catch all exceptions (or a list of them), and want to print out the name of the exception in an error message.

You might want to check out the standard library’s traceback module, which has functions that do some nice formatting of exceptions and tracebacks.

@delnan this situation arises when you are testing if a function is raising an exception as programmed

I needed something like this to DRY up some code: several exceptions can be raised by the method I’m calling, each are handled with their own except statement, but the log entry is very similar in each case.

7 Answers 7

Here are a few different ways to get the name of the class of the exception:

  1. type(exception).__name__
  2. exception.__class__.__name__
  3. exception.__class__.__qualname__
try: foo = bar except Exception as exception: assert type(exception).__name__ == 'NameError' assert exception.__class__.__name__ == 'NameError' assert exception.__class__.__qualname__ == 'NameError' 

If you want the fully qualified class name (e.g. sqlalchemy.exc.IntegrityError instead of just IntegrityError ), you can use the function below, which I took from MB’s awesome answer to another question (I just renamed some variables to suit my tastes):

def get_full_class_name(obj): module = obj.__class__.__module__ if module is None or module == str.__class__.__module__: return obj.__class__.__name__ return module + '.' + obj.__class__.__name__ 
try: # except sqlalchemy.exc.SQLAlchemyError as e: print(get_full_class_name(e)) # sqlalchemy.exc.IntegrityError 

You can print the exception using some formated strings:

try: #Code to execute except Exception as err: print(f" was raised: ") 

You can also use sys.exc_info() . exc_info() returns 3 values: type, value, traceback. On documentation: https://docs.python.org/3/library/sys.html#sys.exc_info

import sys try: foo = bar except Exception: exc_type, value, traceback = sys.exc_info() assert exc_type.__name__ == 'NameError' print "Failed with exception [%s]" % exc_type.__name__ 

This works, but it seems like there must be an easier, more direct way?

try: foo = bar except Exception as exception: assert repr(exception) == '''NameError("name 'bar' is not defined",)''' name = repr(exception).split('(')[0] assert name == 'NameError' 

Replace except Exception as exception with the type of exception you’d like to catch, i.e. except NameError as exception .

The other answers here are great for exploration purposes, but if the primary goal is to log the exception (including the name of the exception), perhaps consider using logging.exception instead of print?

When you say «name» this could mean a couple of things: it could mean only the «immediate» classname, or it could mean the fully qualified name. Usually the latter will be much more useful and less error-prone: I’ve come across more than one case of 2 or more types with same «immediate» classname but from different packages.

If you want to print or log the fully qualified name this is one of the simplest things to do:

try: do_something() except BaseException as e: logger.error(f'whoops! : ') # or maybe print(f'whoops! : ', file=sys.stderr) 

The fully qualified classname will then be printed out like this: «», and then be followed by the exception message. The OP says he wants «for example», to print a message, so assert statements as in the chosen answer don’t seem to be called for.

The answer by MrName is also not irrelevant, and does make a sensible suggestion! if in the above you replaced logger.error(. ) with logger.exception(‘whoops!’) (NB a user message is a required param) you’d get your exception’s fully qualified name logged, not to mention its message, and a stack trace for free.

PS as suggested by the name, JSONDecodeError in my example is an Error , not an Exception (it is a subclass of ValueError ). Catching BaseException (the superclass of both Error and Exception ) usually makes life easier when you’re not fishing for a specific exception. The OP says he wants to catch «all» exceptions.

Источник

Getting the exception value in Python

Also, most exception classes will have an args attribute. Often, args[0] will be an error message.

It should be noted that just using str will return an empty string if there’s no error message whereas using repr as pyfunc recommends will at least display the class of the exception. My take is that if you’re printing it out, it’s for an end user that doesn’t care what the class is and just wants an error message.

It really depends on the class of exception that you are dealing with and how it is instantiated. Did you have something in particular in mind?

repr(e) is also helpful if you want to get the full exception( e.g. NameError(«global name ‘variable’ is not defined»,), instead of «global name ‘variable’ is not defined»

this answer is dangerous, as it will fail for unicode exceptions like this: raise Exception(u’jörn’) . The failure is especially bad, because you will never see the actual exception but just a UnicodeDecodeError . If you don’t know the exception’s encoding (and most of the time you don’t), you should either work on repr(e) or if you really need to, use another try-except block in your exception handling which catches UnicodeDecodeErrors and falls back to repr(e) .

Agree with @JörnHees. I cannot count the number of times that str (or even unicode or .format ) has caused bugs due to Unicode handling. If you don’t have complete control of the error message contents, ALWAYS use repr to avoid unexpected Unicode errors.

Use repr() and The difference between using repr and str

>>> try: . print(x) . except Exception as e: . print(repr(e)) . NameError("name 'x' is not defined") 
>>> try: . print(x) . except Exception as e: . print(str(e)) . name 'x' is not defined 

ah, repr is useful thanks, it seems anything else unicode , str , encoding, . may raise an exception depending on input. Not quite useful when trying to keep the exception to look, but repr is exception-safe it seems

This is much better than any str() -like solutions, because it actually includes the type of exception. With str() I got ‘status’ while with repr() I got KeyError(‘status’) and I was like «aaaaah, now I understand the error».

Even though I realise this is an old question, I’d like to suggest using the traceback module to handle output of the exceptions.

Use traceback.print_exc() to print the current exception to standard error, just like it would be printed if it remained uncaught, or traceback.format_exc() to get the same output as a string. You can pass various arguments to either of those functions if you want to limit the output, or redirect the printing to a file-like object.

Normally I prefer either str() or repr() for a warning or info entry with sys.stdout.write() when I want to show what happened in the background. But, the traceback can be good for when there’s a need to show the full error trace without allowing your program to end.

Another way hasn’t been given yet:

try: 1/0 except Exception, e: print e.message 
integer division or modulo by zero 

args[0] might actually not be a message.

str(e) might return the string with surrounding quotes and possibly with the leading u if unicode:

'integer division or modulo by zero' 

repr(e) gives the full exception representation which is not probably what you want:

"ZeroDivisionError('integer division or modulo by zero',)" 

My bad . It seems that BaseException.message has been deprecated from 2.6 , finally, it definitely seems that there is still not a standardized way to display exception messages. So I guess the best is to do deal with e.args and str(e) depending on your needs (and possibly e.message if the lib you are using is relying on that mechanism).

For instance, with pygraphviz , e.message is the only way to display correctly the exception, using str(e) will surround the message with u» .

But with MySQLdb , the proper way to retrieve the message is e.args[1] : e.message is empty, and str(e) will display ‘(ERR_CODE, «ERR_MSG»)’

Источник

Python: how to get the *full* name of the function I am in

EDIT: The point here is for ‘log’ function to be able to retrieve its caller name on its own (using traceback, inspect, or any mean necessary). I do not want to pass the class name, or anything else than ‘message’ to the ‘log’ function.

@AnthonySottile — Yeah, I was just coming to that conclusion myself — though there is an (imperfect) substitute on pypi (pypi.python.org/pypi/qualname)

@AnthonySottile — Also, from frame objects, I don’t think you actually have a reference back to the function object — Only it’s name.

2 Answers 2

So I finally came up this method:

#!/usr/bin/env python3 def log(message): import inspect import gc code = inspect.currentframe().f_back.f_code func = [obj for obj in gc.get_referrers(code) if inspect.isfunction(obj)][0] print(func.__qualname__, message) 

It needs python3 so that __qualname__ can be used.

The inspect module is very powerful, and can be used in a similar fashion to the way you use traceback to get the name of the function, and probably also the class name. But you can simply make use of the fact that you have the self instance variable, which knows of its own type/class:

import inspect class cls(object): def f1(self): this_class_name = type(self).__name__ this_func_name = inspect.currentframe().f_code.co_name print(this_class_name, this_func_name) mycls = cls() mycls.f1() 

Источник

Читайте также:  Html ячейка без переноса
Оцените статью