如何将捕获的异常(其描述和堆栈跟踪)转换为外部使用的str ?

try:
    method_that_can_raise_an_exception(params)
except Exception as e:
    print(complete_exception_description(e))

当前回答

我的2美分。

import sys, traceback
try: 
  ...
except Exception, e:
  T, V, TB = sys.exc_info()
  print ''.join(traceback.format_exception(T,V,TB))

其他回答

我的2美分。

import sys, traceback
try: 
  ...
except Exception, e:
  T, V, TB = sys.exc_info()
  print ''.join(traceback.format_exception(T,V,TB))

如果你想将你的回溯转换为dict的列表(适用于python > 3.5):

from traceback import TracebackException


def list_traceback(exc_value: BaseException):
    result = list()

    # get previous fails, so errors are appended by order of execution
    if exc_value.__context__:
        result += list_traceback(exc_value.__context__)

    # convert Exception into TracebackException
    tbe = TracebackException.from_exception(exc_value)

    # get stacktrace (cascade methods calls)
    error_lines = list()
    for frame_summary in tbe.stack:
        summary_details = {
            'filename': frame_summary.filename,
            'method'  : frame_summary.name,
            'lineno'  : frame_summary.lineno,
            'code'    : frame_summary.line
        }
        error_lines.append(summary_details)

    # append error, by order of execution
    result.append({"error_lines": error_lines,
                   "type"       : tbe.exc_type.__name__,
                   "message"    : str(tbe)})

    return result

这将是结果(一个例子):

[
   {
      "error_lines": [
         {
            "filename": "/home/demo/file2.py",
            "method": "do_error_2",
            "lineno": 18,
            "code": "a=1/0"
         }
      ],
      "type": "ZeroDivisionError",
      "message": "division by zero"
   },
   {
      "error_lines": [
         {
            "filename": "/home/demo/file_main.py",
            "method": "demo2",
            "lineno": 50,
            "code": "file2.DEMO().do_error_2()"
         },
         {
            "filename": "/home/demo/file2.py",
            "method": "do_error_2",
            "lineno": 20,
            "code": "raise AssertionError(\"Raised inside the except, after division by zero\")"
         }
      ],
      "type": "AssertionError",
      "message": "Raised inside the except, after division by zero"
   }
]

对于Python 3.5+ 使用回溯。TracebackException,它可以处理在任何地方捕获的异常。

def print_trace(ex: BaseException):
    print(''.join(traceback.TracebackException.from_exception(ex).format()))

例子

import traceback

try:
    1/0
except Exception as ex:
    print(''.join(traceback.TracebackException.from_exception(ex).format()))

> >输出

Traceback (most recent call last):
  File "your_file_name_here.py", line 29, in <module>
    1/0
ZeroDivisionError: division by zero

它与from_exec()和format_exception()相同:

    a = ''.join(traceback.TracebackException.from_exception(ex).format())
    b = traceback.format_exc()
    c = ''.join(traceback.format_exception(type(ex), ex, ex.__traceback__))
    print(a == b == c)  # This is True !!

对于使用Python-3的用户

使用回溯模块和异常。__traceback__可以提取堆栈跟踪,如下所示:

使用traceback.extract_stack()获取当前堆栈跟踪 删除最后三个元素(因为它们是堆栈中的条目,使我找到了调试函数) 使用traceback.extract_tb()从异常对象中追加__traceback__ 使用traceback.format_list()格式化整个内容

import traceback
def exception_to_string(excp):
   stack = traceback.extract_stack()[:-3] + traceback.extract_tb(excp.__traceback__)  # add limit=?? 
   pretty = traceback.format_list(stack)
   return ''.join(pretty) + '\n  {} {}'.format(excp.__class__,excp)

一个简单的演示:

def foo():
    try:
        something_invalid()
    except Exception as e:
        print(exception_to_string(e))

def bar():
    return foo()

当我们调用bar()时,我们得到以下输出:

  File "./test.py", line 57, in <module>
    bar()
  File "./test.py", line 55, in bar
    return foo()
  File "./test.py", line 50, in foo
    something_invalid()

  <class 'NameError'> name 'something_invalid' is not defined

如果你的目标是让异常和stacktrace消息看起来与python抛出错误时完全一样,那么以下代码在python 2+3中都适用:

import sys, traceback


def format_stacktrace():
    parts = ["Traceback (most recent call last):\n"]
    parts.extend(traceback.format_stack(limit=25)[:-2])
    parts.extend(traceback.format_exception(*sys.exc_info())[1:])
    return "".join(parts)

# EXAMPLE BELOW...

def a():
    b()


def b():
    c()


def c():
    d()


def d():
    assert False, "Noooh don't do it."


print("THIS IS THE FORMATTED STRING")
print("============================\n")

try:
    a()
except:
    stacktrace = format_stacktrace()
    print(stacktrace)

print("THIS IS HOW PYTHON DOES IT")
print("==========================\n")
a()

它的工作原理是从堆栈中删除最后一个format_stacktrace()调用,并加入其余的调用。当运行时,上面的示例给出以下输出:

THIS IS THE FORMATTED STRING
============================

Traceback (most recent call last):
  File "test.py", line 31, in <module>
    a()
  File "test.py", line 12, in a
    b()
  File "test.py", line 16, in b
    c()
  File "test.py", line 20, in c
    d()
  File "test.py", line 24, in d
    assert False, "Noooh don't do it."
AssertionError: Noooh don't do it.

THIS IS HOW PYTHON DOES IT
==========================

Traceback (most recent call last):
  File "test.py", line 38, in <module>
    a()
  File "test.py", line 12, in a
    b()
  File "test.py", line 16, in b
    c()
  File "test.py", line 20, in c
    d()
  File "test.py", line 24, in d
    assert False, "Noooh don't do it."
AssertionError: Noooh don't do it.