背景
通常使用traceback.format_exc()捕捉异常,其会把异常的堆栈信息打印出来形成字符串返回,但是有时候返回信息过多,所以就想了解一下用法。
参数说明
format_exc(limit=None, chain=True) limit:打印最后的 abs(limit) 条目 chain:如果chain为true(默认值),则也将打印链接异常(异常的 _cause_ 或 _context_ 属性),就像解释器本身在打印未处理的异常时所做的那样
- test.py
- import traceback
- import requests
-
- def f():
- try:
- requests.get('http://1.1.1.1', timeout=0.1)
- except:
- print(traceback.format_exc(limit=2, chain=False))
-
-
- if __name__ == '__main__':
- print(123)
- f()
- print(456)
-
- 输出:
-
- 123
- Traceback (most recent call last):
- File "D:/software/work/code/test/traceback_test.py", line 13, in f
- requests.get('http://1.1.1.1', timeout=0.1)
- File "D:\software\work\code\test\venv\lib\site-packages\requests\api.py", line 72, in get
- return request('get', url, params=params, **kwargs)
- requests.exceptions.ConnectTimeout: HTTPConnectionPool(host='1.1.1.1', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x00000216B10256A0>, 'Connection to 1.1.1.1 timed out. (connect timeout=0.1)'))
-
- 456
-
-
- test2.py
- import traceback
- import requests
-
- def f():
- try:
- requests.get('http://1.1.1.1', timeout=0.1)
- except:
- print(traceback.format_exc(limit=1, chain=False))
-
-
- if __name__ == '__main__':
- print(123)
- f()
- print(456)
-
- 输出
- 123
- Traceback (most recent call last):
- File "D:/software/work/code/test/traceback_test.py", line 13, in f
- requests.get('http://1.1.1.1', timeout=0.1)
- requests.exceptions.ConnectTimeout: HTTPConnectionPool(host='1.1.1.1', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x0000012A61875630>, 'Connection to 1.1.1.1 timed out. (connect timeout=0.1)'))
-
- 456
-
获取线程中的异常信息
通常情况下我们无法将多线程中的异常带回主线程,所以也就无法打印线程中的异常,而通过上边学到这些知识,我们可以对线程做如下修改,从而实现捕获线程异常的目的。
- 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()
-
- 输出:
- 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
-
参考链接
https://www.docs4dev.com/docs/zh/python/3.7.2rc1/all/library-traceback.html