Tue
Tue

Reputation: 432

Python exception handling, detecting the function that caused the exception?

I'm trying to implement some decent exception handling in a project. I have set up the following dummy example of what my code looks like:

def task1():
    pass


def task2():
    """Generic docstring"""
    a = 4
    b = c


def task3():
    pass


def task4():
    pass


def main():
    try:
        task1()
        task2()
        task3()
        task4()
    except Exception as ex:
        print(ex)
    finally:
        print("All done")
main()

The above code almost does what I want. It prints the error that happened (I will log it in a file in the real code), but unfortunately it does not tell me in which subfunction the exception is triggered, and I don't see any options for getting this information. I guess I could have a separate try/except block in each subfunction that raises a message from that function, but I would prefer if I didn't have to do this and could get the information automatically.

Since my experience with error handling is rather limited, I am also very eager to hear if anyone has alternative / better solutions to how I should implement the error handling.

My use case is that I need to run this piece of code in parallel and it is very error prone since it is being run on a bunch of external files and sometimes these files just contains errors and other times the format they are in isn't quite what my code expects. I need to run millions of files and I don't want a single error to stop anything, I just want it logged in a file, such that I can later look at the errors and determine whether these are fixable errors or not.

Edit, based on the link provided by @timgeb I created the following, which does the job but isn't all that pretty.

import sys, traceback

def task1():
    pass


def task2():
    """Generic docstring"""
    a = 4
    b = c


def task3():
    pass


def task4():
    pass


def main():
    try:
        task1()
        task2()
        task3()
        task4()
    except Exception as ex:
        tb = sys.exc_info()[-1]
        stk = traceback.extract_tb(tb, -1)
        fname = stk[0][2]
        print(f'The failing function was {fname} with error message {ex}')
    finally:
        print("All done")
main()

Upvotes: 1

Views: 52

Answers (1)

chepner
chepner

Reputation: 530960

You can use a loop, so that the loop index remains assigned to the last function attempted.

try:
    for x in [task1, task2, task3, task4]:
        x()
except Exception as ex:
    print(f'{ex} raised by {x}')
finally:
    print("All done")

Upvotes: 3

Related Questions