【问题标题】:How can you programmatically inspect the stack trace of an exception in Python?如何以编程方式检查 Python 中异常的堆栈跟踪?
【发布时间】:2010-03-01 21:37:14
【问题描述】:

当 Python 发生异常时,你能检查堆栈吗?你能确定它的深度吗?我查看了traceback 模块,但不知道如何使用它。

我的目标是捕获在解析 eval 表达式期间发生的任何异常,而不捕获它可能调用的任何函数引发的异常。不要因为我使用 eval 而责备我。这不是我的决定。

注意:我想以编程方式执行此操作,而不是交互方式。

【问题讨论】:

    标签: python exception-handling stack-trace traceback


    【解决方案1】:

    traceback 就足够了——我想文档描述得很好。简化示例:

    import sys
    import traceback
    
    try:
        eval('a')
    except NameError:
        traceback.print_exc(file=sys.stdout)
    

    【讨论】:

    • 我不想打印回溯。我正在尝试检查它。这如何告诉我异常是发生在 eval 文本本身中,还是发生在被评估文本调用的函数中?
    • 如果 eval 文本错误,可能会引发许多不同类型的错误。我最终使用了检查并查看了回溯的深度,以查看错误是由评估原始文本引起的,还是在被调用函数的主体中。
    【解决方案2】:

    您可以使用inspect 模块,该模块具有一些用于跟踪的实用功能。查看框架对象的overview of properties

    【讨论】:

      【解决方案3】:

      我喜欢回溯模块。

      您可以使用sys.exc_info() 获取回溯对象。然后,您可以使用该对象获取使用traceback.extract_tb() 的回溯条目列表预处理列表。然后您可以使用traceback.format_list() 获取可读列表,如下所示:

      import sys
      import traceback, inspect
      
      try:
          f = open("nonExistant file",'r')
      except:
          (exc_type, exc_value, exc_traceback) = sys.exc_info()
          #print exception type
          print exc_type
          tb_list = traceback.extract_tb(sys.exc_info()[2])
          tb_list = traceback.format_list(tb_list)
          for elt in tb_list:
              print elt
              #Do any processing you need here.
      

      查看系统模块:http://docs.python.org/library/sys.html

      以及回溯模块:http://docs.python.org/library/traceback.html

      【讨论】:

        【解决方案4】:

        你定义了这样一个函数(doc here):

        def raiseErr():
           for f in inspect.stack(): print '-', inspect.getframeinfo(f[0])
        

        并从您的模块中调用它:

        raiseErr()
        

        函数 raiseErr 将打印有关您调用它的位置的信息。

        更详细一点,你可以这样做:

        import inspect, traceback
        A = [inspect.getframeinfo(f[0]) for f in inspect.stack()]
        print "traceback structure fields:", filter(lambda s: s[0] != '_', dir(A[0]))
        print A[0].filename, A[0].lineno
        for f in inspect.stack():
            F = inspect.getframeinfo(f[0])
            print '-', F.filename, F.lineno, '\t', F.code_context[0].strip()
        

        其他可能性是定义这个函数:

        def tr():
            print '* - '*10,
            print sys._getframe(1).f_code.co_name
        

        并在您想要跟踪的地方调用它。如果您想要所有跟踪,请在 _getframe(1) 中从 1 向上创建一个迭代器。

        【讨论】:

          【解决方案5】:

          除了 AndiDog 对 inspect 的回答之外,请注意 pdb 允许您在堆栈中上下导航,检查本地人等。标准库中的源代码pdb.py 可以帮助您学习如何做这些事情。

          【讨论】:

            猜你喜欢
            • 2011-01-05
            • 2017-08-06
            • 2010-09-13
            • 1970-01-01
            • 2012-09-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多