Search code examples
pythontry-catch

Get the exactly error line in try catch (error line in a subfile)


I'm developing a python bot and the debug sucks, when I use try catch to handle exceptions.

I need to get the right error line, when error occurs in a subfile, where I'm import a function. Following, is an example:

My files structure:

  • div.py
  • main.py

div.py:

def div(n):
    return n / 0

main.py:

from div import div
import sys

try: 
    print(div(5))
except Exception as e: 
    exception_type, exception_object, exception_traceback = sys.exc_info()
    filename = exception_traceback.tb_frame.f_code.co_filename
    line_number = exception_traceback.tb_lineno

    print("Exception type: ", exception_type)
    print("File name: ", filename)
    print("Line number: ", line_number) # return line 5
    print("Error: ", e)

I was expecting get the line 2 in 'print("Line number: ", line_number)', because the error occurs in line 2 in div.py, but return line 5, where I call the function.

I search how get error lines in try catch, but I only find solutions like this, where return error line in main file, but not in subfile.


Solution

  • Here's an example extracting the last stack frame which gives what you want:

    import traceback
    from div import div
    import sys
    
    try: 
        print(div(5))
    except Exception as e:
        exception_type, exception_object, exception_traceback = sys.exc_info()
        last_frame = traceback.extract_tb(exception_traceback)[-1]
        print("Exception type: ", exception_type.__name__)
        print("File name: ", last_frame.filename)
        print("Line number: ", last_frame.lineno)
        print("Error: ", e)
    

    Output:

    Exception type:  ZeroDivisionError
    File name:  C:\Users\metolone\div.py
    Line number:  2
    Error:  division by zero
    

    You could also walk the frame formatting as you like:

    import traceback
    from div import div
    import sys
    
    try: 
        print(div(5))
    except Exception as e:
        exception_type, exception_object, exception_traceback = sys.exc_info()
        tb = traceback.extract_tb(exception_traceback)
        print("Exception type: ", exception_type.__name__)
        print("Error: ", e)
        for frame in tb:
            print(f'File: {frame.filename}({frame.lineno}):\n  {frame.line}')
    

    Output:

    Exception type:  ZeroDivisionError
    Error:  division by zero
    File: C:\Users\metolone\test.py(6):
      print(div(5))
    File: C:\Users\metolone\div.py(2):
      return n / 0