1
\$\begingroup\$

I'm trying to write a Exception Handling class in Python so that I can re-use. If you have any ideas on how I can improve this to output more detailed information I would appreciate it:

class EHandle:
    @staticmethod
    def printit():
        exc_type, exc_obj, exc_tb = sys.exc_info()
        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
        print(exc_type, fname, exc_tb.tb_lineno)
        frm = inspect.trace()[-1]
        mod = inspect.getmodule(frm[0])
        modname = mod.__name__ if mod else frm[1]
        print 'Thrown from', modname

And I call the class and method like below:

try:
    ggg()
    runafunction()
except:
    EHandle.printit()
    sys.exit()
\$\endgroup\$
1
  • 2
    \$\begingroup\$ The traceback itself holds a lot of information. You can print it with traceback.print_exc() \$\endgroup\$
    – zondo
    Commented Apr 26, 2016 at 0:01

1 Answer 1

4
\$\begingroup\$

Python's built-in exception traceback gives us:

Traceback (most recent call last):
  File "D:/code/python/error.py", line 43, in <module>
    error()
  File "D:/code/python/error.py", line 28, in error
    another_level()
  File "D:/code/python/error.py", line 31, in another_level
    return tuple()[0]
IndexError: tuple index out of range

Where your code gives us:

(<type 'exceptions.IndexError'>, 'error.py', 39)
Thrown from __main__

So yours is sparse from the go. But what makes it bad is line 39 is where I call error(). It's not where the error happens, that's line 31. It also doesn't give us the path to the file, if I have multiple files with the same name then your program is going to cause me some serious headaches. And finally the error doesn't throw in __main__ it throws in another_level.

If you are ok with printing the exact same as Python then, as zondo said, you can just change your code to:

def printit():
    traceback.print_exc()

As you probably want to format it yourself, and be able to change the data. You should use sys.exc_info() and traceback.extract_tb(exc_traceback). And so if you wanted to implement print_exc yourself you can use:

def print_exc():
    exc_type, exc_value, exc_traceback = sys.exc_info()
    print 'Traceback (most recent call last):'
    print '\n'.join([
        '  File "{}", line {}, in {}\n    {}'.format(*level)
        for level in traceback.extract_tb(exc_traceback)])
    print '{}: {}\n'.format(exc_type.__name__, exc_value)

This allows you to format the error however you want.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.