【问题标题】:Extract full trace from exception object从异常对象中提取完整跟踪
【发布时间】:2021-07-13 17:39:17
【问题描述】:

我关注this answer并实现了以下内容:

def B():
    try:
        raise Exception()
    except Exception as e:
        traceback_ob = e.__traceback__

        import traceback
        traceback_str = ''.join(traceback.format_exception(etype=type(e), value=e, tb=traceback_ob))

        print(traceback_str)

def A():
    B()

A()

输出是:

Traceback (most recent call last):
  File "/path/bespoke_traceback.py", line 3, in B
    raise Exception()
Exception

我需要完整的跟踪,所以在字符串中包含 A - 我怎样才能做到这一点?

具体来说——我需要这个字符串,而不仅仅是打印出来的。

【问题讨论】:

标签: python


【解决方案1】:

你可以简单地使用日志模块来实现回溯,不需要其他模块:

对于同一个文件,异常回溯将来自直接类。如果是从不同文件调用,logger.exception 将打印整个回溯

查看以下示例:

import logging
logger = logging.getLogger(__name__)
def B():
    try:
        raise Exception()
    except Exception as e:
        logger.exception("Error",stack_info=True)

def A():
    B()

A()

【讨论】:

  • 这给出了与问题完全相同的输出......
  • @Tomerikoo 在异常调用中添加stack_info=True。检查更新的答案
  • 我已经编辑了这个问题 - 我需要它在一个字符串中,而不仅仅是打印 - 我可以从记录器中得到它吗?
  • traceback.print_stack() 也可以达到同样的效果,logging 不需要,但这不是预期的输出...
【解决方案2】:

我的个人方法:(很抱歉使用文件,但它似乎是唯一的解决方案) 有点复杂,抱歉

from threading import Thread
import sys
import os

def B():
    raise Exception()
    
def A():
    B()

def catch_error(f):
    # redirect stderr (where errors are printed) to a temporary file
    # tried StringIO but it only showed part of the exception
    sys.stderr = open('temp', 'w')

    # run it in a thread so that the script doesn't stop after the error
    t = Thread(target=A) 
    t.start()
    t.join()

    # close the file and return stderr back to normal
    sys.stderr.close()
    sys.stderr = sys.__stderr__

    # get error string from the file and then delete it
    s = open('temp', 'r').read()
    os.remove('temp')

    # remove some lines concerning the threading module
    lines = s.split('\n')
    [lines.pop(2) for i in range(4)]
    lines.pop(0)

    # join the lines and return
    return '\n'.join(lines)

print(catch_error(A))

输出:

Traceback (most recent call last):
  File "C:\Users\lenovo\Amin\Workspace\test.py", line 9, in A
    B()
  File "C:\Users\lenovo\Amin\Workspace\test.py", line 6, in B
    raise Exception()
Exception

【讨论】:

    【解决方案3】:

    您可以将format_exception 函数与format_stack 组合起来获取之前的帧:

    import traceback
    
    def B():
        try:
            raise Exception("error")
        except Exception as e:
            exception = traceback.format_exception(etype=type(e), value=e, tb=e.__traceback__)
            stack = traceback.format_stack()
    
            # exception already holds the last (current) frame - we just want to add the previous frames
            exception[1:1] = stack[:-1]
    
            traceback_str = ''.join(exception)
            print(traceback_str)
    
    def A():
        B()
    
    A()
    

    将给予:

    Traceback (most recent call last):
      File "test.py", line 16, in <module>
        A()
      File "test.py", line 14, in A
        B()
      File "test.py", line 5, in B
        raise Exception("error")
    Exception: error
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-13
      • 2011-08-30
      • 2018-09-06
      • 1970-01-01
      • 1970-01-01
      • 2021-10-08
      • 2010-09-05
      • 2015-10-03
      相关资源
      最近更新 更多