The correct way to handle traces of an exception stack in Python

I am writing code that can throw exceptions on the stack, and I have a layer closer to the top that catches these exceptions and sends them for processing by the error handling module. I would like the error handling module to be able to print a stack trace in the error log, but it's hard for me to figure out how to do this.

Some notes on the background:

  • The code is multithreaded, so I'm not sure about the behavior of sys.last_traceback

  • I tried to grab the stack in the constructor of the exception itself. sys.last_traceback is sometimes absent in this case (since it exists only in the case of unhandled exceptions) and is not always correct. I am currently using

    self.stack = traceback.format_stack () [: - 2]

in the exception constructor, and although this looks promising in terms of information, it doesn't seem like the β€œright” way to do it

  • All examples of how to do this, what I could find, show how to print the stack trace in the exception block, and not in some later error handling module, and it looks different in the behavior from what I want. (see, for example, Printing the current call stack from a method in Python code )

  • I earned a trace module in python docs ( http://docs.python.org/library/traceback.html ) and was unable to figure out if this really does what I want. It seems that this mainly concerns formatting tracebacks, which you can get from sys.last_traceback. It has some use cases, and none of them match what I'm trying to do.

I do not believe that I am the first person who ever wanted to do this, so I have to miss something. Any pointers in the right direction are greatly appreciated.

+6
source share
3 answers

Your first line to handle the exception might be:

exc_type, exc_value, exc_traceback = sys.exc_info() 

You can save these variables or pass them as you like, and then use the trace module to display them.

+2
source

How about adding a decorator to the functions you want to protect? For instance:

 @onerrorignore def foo(a, b, c): ... 

the decorator will look something like this:

 def onerrorignore(f): def _f(*args, **kwargs): try: ret = f() except: error_handler.handle(sys.exc_info()) else: return ret return _f 
0
source

If I understand you correctly, do you want to throw an exception while maintaining stacktrace? So you have a call hierarchy:

 error_handling_module # you want to print the stacktrace here | something_else | module_excepting_and_rethrowing | something_else | module_raising_an_error 

In your module_excepting_and_rethrowing you can do:

 except Exception: exc_type, exc_value, exc_traceback = sys.exc_info() raise NewException, exc_value, exc_traceback 

In Python3, you can also:

  except Exception as e: raise NewException from e 
0
source

Source: https://habr.com/ru/post/912917/


All Articles