When we first approached Python, simple exception handling has helped us solve most of the problems, but as we go deeper, we'll find that there are a lot of situations where simple exception handling doesn't solve the problem, and the following code, simple print exceptions, can provide very limited information.
def func1():
raise Exception("--func1 exception--")
def main():
try:
func1()
except Exception as e:
print e
if __name__ == '__main__':
main()
After execution the output is as follows:
exception--
By example, we find that ordinary print exceptions have very little information (usually the value of an exception), in which case it is difficult to locate the problem in which block of code, and how this exception occurs. So how exactly do you want to print more detailed information? Let's take a brief introduction.
Sys.exc_info and Traceback Object
The traceback information of a Python program is derived from an object called Traceback object, and this Traceback object is usually obtained by means of a function sys.exc_info (), which takes a first example:
import sys
def func1():
raise NameError("--func1 exception--")
def main():
try:
func1()
except Exception as e:
exc_type, exc_value, exc_traceback_obj = sys.exc_info()
print "exc_type: %s" % exc_type
print "exc_value: %s" % exc_value
print "exc_traceback_obj: %s" % exc_traceback_obj
if __name__ == '__main__':
main()
After execution the output is as follows:
exc_type: <type 'exceptions.NameError'>
exc_value: --func1 exception--
exc_traceback_obj: <traceback object at 0x7faddf5d93b0>
As we can see from the above example, Sys.exc_info () Gets the information about the currently processed exception, returns a tuple, the first data of the tuple is the type of the exception (example is the Nameerror type), the second return value is the value of the exception, The third one is the Traceback object we want.
With Traceback object we can print and format traceback information via Traceback module, so let's take a look at the related functions of Traceback module.
Traceback Module
Python's Traceback module provides a complete set of interfaces for extracting, formatting, and printing the stack traces information for Python programs, which we'll look at in more detail in the following examples:
Print_tb
import sys
import traceback
def func1():
raise NameError("--func1 exception--")
def main():
try:
func1()
except Exception as e:
exc_type, exc_value, exc_traceback_obj = sys.exc_info()
traceback.print_tb(exc_traceback_obj)
if __name__ == '__main__':
main()
Output:
File "<ipython-input-23-52bdf2c9489c>", line 11, in main
func1()
File "<ipython-input-23-52bdf2c9489c>", line 6, in func1
raise NameError("--func1 exception--")
Here we can find the print exception information more detailed, below we understand the following PRINT_TB details:
traceback.print_tb(tb[, limit[, file]])
- TB: This is Traceback object, which we get through sys.exc_info.
- Limit: This is the stack trace level that is restricted, and if not set or none, all layers of stack trace are printed
- File: This is the output stream that sets the print, can be a file, or it can be a File-like object such as stdout. If not or none, the output is to Sys.stderr.
Print_exception
import sys
import traceback
def func1():
raise NameError("--func1 exception--")
def func2():
func1()
def main():
try:
func2()
except Exception as e:
exc_type, exc_value, exc_traceback_obj = sys.exc_info()
traceback.print_exception(exc_type, exc_value, exc_traceback_obj, limit=2, file=sys.stdout)
if __name__ == '__main__':
main()
Output:
Traceback (most recent call last):
File "<ipython-input-24-a68061acf52f>", line 13, in main
func2()
File "<ipython-input-24-a68061acf52f>", line 9, in func2
func1()
NameError: --func1 exception--
Look at the definition:
traceback.print_exception(etype, value, tb[, limit[, file]])
- Two more parameters EType and value than PRINT_TB, respectively exception type and exception value, plus TB (Traceback object), exactly the three values returned by Sys.exc_info ()
- In addition, compared with PRINT_TB, printing information more than the beginning of the "Traceback (most ...)" Information and the exception type and value information for the last line
- Another difference is that when the exception is SyntaxError, there will be "^" to indicate the location of the syntax error
Print_exc
Print_exc is a simplified version of print_exception, because exception type, both value and Traceback object can be obtained through sys.exc_info (), so Print_exc () automatically executes exc _info () to help get these three parameters, and therefore this function is the most commonly used in our program, because it is simple enough
import sys
import traceback
def func1():
raise NameError("--func1 exception--")
def func2():
func1()
def main():
try:
func2()
except Exception as e:
traceback.print_exc(limit=1, file=sys.stdout)
if __name__ == '__main__':
main()
Output (because of limit=1, so only one level is printed out):
Traceback (most recent call last):
File "<ipython-input-25-a1f5c73b97c4>", line 13, in main
func2()
NameError: --func1 exception--
Defined as follows:
traceback.print_exc([limit[, file]])
- Only two parameters, simple enough
Format_exc
import logging
import sys
import traceback
logger = logging.getLogger("traceback_test")
def func1():
raise NameError("--func1 exception--")
def func2():
func1()
def main():
try:
func2()
except Exception as e:
logger.error(traceback.format_exc(limit=1, file=sys.stdout))
if __name__ == '__main__':
main()
From this example we can see that sometimes we want a string, for example, we would like to log the exception through logger, this time we need to format_exc, this is the most common function, it is the same as PRINT_EXC usage, It just doesn't print directly but returns a string.
There are some other functions in the Traceback module, but because it is not commonly used, it is not possible to expand, interested students can look at the reference link in the document.
Gets the exception information in the thread
Normally we cannot bring the exception in the multithreading back to the main thread, so we cannot print the exceptions in the threads, and by learning this knowledge, we can make the following modifications to the thread to achieve the purpose of catching the thread exception.
The following example is from a blog post in Weidong and is slightly modified (see the reference link)
import threading
import traceback
def my_func():
raise BaseException("thread exception")
class ExceptionThread(threading.Thread):
def __init__(self, group=None, target=None, name=None, args=(), kwargs=None, verbose=None):
"""
Redirect exceptions of thread to an exception handler.
"""
threading.Thread.__init__(self, group, target, name, args, kwargs, verbose)
if kwargs is None:
kwargs = {}
self._target = target
self._args = args
self._kwargs = kwargs
self._exc = None
def run(self):
try:
if self._target:
self._target()
except BaseException as e:
import sys
self._exc = sys.exc_info()
finally:
#Avoid a refcycle if the thread is running a function with
#an argument that has a member that points to the thread.
del self._target, self._args, self._kwargs
def join(self):
threading.Thread.join(self)
if self._exc:
msg = "Thread '%s' threw an exception: %s" % (self.getName(), self._exc[1])
new_exc = Exception(msg)
raise new_exc.__class__, new_exc, self._exc[2]
t = ExceptionThread(target=my_func, name='my_thread')
t.start()
try:
t.join()
except:
traceback.print_exc()
The output is as follows:
Traceback (most recent call last):
File "/data/code/testcode/thread_exc.py", line 43, in <module>
t.join()
File "/data/code/testcode/thread_exc.py", line 23, in run
self._target()
File "/data/code/testcode/thread_exc.py", line 5, in my_func
raise BaseException("thread exception")
Exception: Thread 'my_thread' threw an exception: thread exception
Geekpy
Links: www.jianshu.com/p/a8cb5375171a
Source: Pinterest
The copyright of Jane's book is owned by the author, please contact the author in any form for authorization and attribution.