Paul1911
Paul1911

Reputation: 193

Proper General Exception Handling after User-Defined Exception Handling

I logically want to connect a user defined exception with general exception handling. Firstly, it should be checked whether the user defined exception is triggered. If it is not triggered, but another exception occurs, I want to print the exception information by get_exception_info().

I have the following code:

class TestException(Exception):
    pass

def get_exception_info():
    try:
        exception_type, exception_value, exception_traceback = sys.exc_info()
        file_name, line_number, procedure_name, line_code = traceback.extract_tb(exception_traceback)[-1] #this line is properly indented in my file
        exception_info = ''.join('[Time Stamp]: '
            + str(time.strftime('%d-%m-%Y %I:%M:%S %p'))
            + '' + '[File Name]: ' + str(file_name) + ' '
            + '[Procedure Name]: ' + str(procedure_name) + ' '
            + '[Error Message]: ' + str(exception_value) + ' '
            + '[Error Type]: ' + str(exception_type) + ' '
            + '[Line Number]: ' + str(line_number) + ' '
            + '[Line Code]: ' + str(line_code))
        return exception_info
    except:
        pass

def test_func(x):

    try:
        if x > 0:
            raise TestException('wrong')
        elif x < 0:
            raise TestException('right')
        else:
            pass
    except TestException as e:
        print(e)
    except Exception:
        exception_info = get_exception_info()
        print(exception_info)
    finally:
        pass

test_func(a) 

Theoretically, this would cause an Exception and it should print out the result of get_exception_info(). However I just get "NameError: name 'a' is not defined.

What am I doing wrong? And, more importantly probably, is this the right way to archieve my goal?

Thank you!

Upvotes: 0

Views: 235

Answers (1)

Paul P
Paul P

Reputation: 3907

The error indicates that the value a which you are passing into test_func() is not defined.

Add a line defining a, e.g.:

# ...
a = "hello"
test_func(a)

EDIT:

For your code to work, you also need to import time, traceback, and sys. I would also suggest not catching exceptions inside get_exception_info(), as this may hide exceptions that you actually want to see, i.e.:

import time
import traceback
import sys

class TestException(Exception):
    pass

def get_exception_info():
    exception_type, exception_value, exception_traceback = sys.exc_info()
    file_name, line_number, procedure_name, line_code = traceback.extract_tb(exception_traceback)[-1]
    exception_info = ' '.join([
        '[Time Stamp]:',
        time.strftime('%d-%m-%Y %I:%M:%S %p'),
        '[File Name]:',
        file_name,
        '[Procedure Name]:',
        procedure_name,
        '[Error Message]:',
        str(exception_value),
        '[Error Type]:',
        str(exception_type),
        '[Line Number]:',
        str(line_number),
        '[Line Code]:',
        line_code,
    ])

    return exception_info
# ...

EDIT II:

It sounds like the question revolves around how to catch an undefined variable (a in this case).

In that case, I would suggest adding a try-except block around the function call, e.g.:

try:
    test_func(a)
except Exception:
    exception_info = get_exception_info()
    print(exception_info)

When a is undefined, this will generate something along the lines of:

[Time Stamp]: 13-06-2021 10:44:31 AM [File Name]: /path/to/sf_exc.py [Procedure Name]: <module> [Error Message]: name 'a' is not defined [Error Type]: <class 'NameError'> [Line Number]: 76 [Line Code]: test_func(a)

Comment

As a general remark, instead of manually formatting the error message, I would use Python's logging module which is powerful and gives a lot of flexibility when it comes to formatting different types of messages, using a custom Formatter. In particular, Formatter comes with methods that can be customised to treat exceptions and stack information.

Upvotes: 1

Related Questions