Elegant handling of Python Traceback

Source: Internet
Author: User
Tags stack trace

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.
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.