什么“<exception caught =”“here =”“>”扭曲的追溯线是什么意思?</exception>

时间:2014-02-06 17:38:50

标签: python debugging twisted

例如:

Unhandled error in Deferred:
Unhandled Error
Traceback (most recent call last):
  File "/opt/zenoss/lib/python/twisted/internet/defer.py", line 388, in errback
    self._startRunCallbacks(fail)
  File "/opt/zenoss/lib/python/twisted/internet/defer.py", line 455, in _startRunCallbacks
    self._runCallbacks()
  File "/opt/zenoss/lib/python/twisted/internet/defer.py", line 542, in _runCallbacks
    current.result = callback(current.result, *args, **kw)
  File "/opt/zenoss/lib/python/twisted/internet/defer.py", line 1076, in gotResult
    _inlineCallbacks(r, g, deferred)
--- <exception caught here> ---
  File "/opt/zenoss/lib/python/twisted/internet/defer.py", line 1018, in _inlineCallbacks
    result = result.throwExceptionIntoGenerator(g)
  File "/opt/zenoss/lib/python/twisted/python/failure.py", line 352, in throwExceptionIntoGenerator
    return g.throw(self.type, self.value, self.tb)
exceptions.TypeError: exceptions must be classes, or instances, not str

如果它被捕获,为什么它仍然传播下面两帧?如何找出抛出的位置?

1 个答案:

答案 0 :(得分:2)

这实际上不是追溯。这就是twisted.python.failure.Failure“打印”自身的方式(虽然确定事情不明确,但执行此操作的方法是printTraceback)。

--- <exception caught here> ---位于中间的原因是它正在划分与异常相关的调用堆栈的两个不同部分相关的信息。

在标记之上,堆栈帧描述了上面的 决定创建Failure实例的异常处理程序(来自异常和回溯状态)。

例如,考虑一下这个简单的程序:

from twisted.python.failure import Failure

def a():
    b()

def b():
    try:
        c()
    except:
        return Failure()

def c():
    1 / 0

f = a()
f.printTraceback()

如果你运行这个,那么你会在标记线上方看到:

File "someprog.py", line 16, in <module>
  f = a()
File "someprog.py", line 5, in a
  return b()

如果调用堆栈是一个堆栈,那么你可以看到这些是在捕获异常并创建Failure的帧之前被推到它上面的两个帧。

在标记线下方,您会得到:

File "someprog.py", line 9, in b
  c()
File "someprog.py", line 14, in c
  1 / 0

这些是调用堆栈中的两个帧,并且被引发的异常弹出。

大多数情况下,只有标记下方的帧才有趣。标记上方的帧以此格式分隔,因为它们通常是Twisted某些部分的深层实现细节。由于Twisted是一个协作式多任务系统,实现中的堆栈帧通常不会告诉您对异常上下文非常有用(因为Python中的协作式多任务系统无法保持正在处理的逻辑操作之间的对应关系)正在进行处理的Python框架对象。)

除此之外,由于所涉及的代码使用inlineCallbacks这一事实,因此了解回溯变得更加复杂。这会对调用堆栈起到进一步的作用,并且通常会破坏你得到的任何回溯。

File "/opt/zenoss/lib/python/twisted/internet/defer.py", line 1018, in _inlineCallbacks
  result = result.throwExceptionIntoGenerator(g)
File "/opt/zenoss/lib/python/twisted/python/failure.py", line 352, in throwExceptionIntoGenerator
  return g.throw(self.type, self.value, self.tb)
exceptions.TypeError: exceptions must be classes, or instances, not str

但是,我注意到的是,尝试通过inlineCallbacks的实现将异常引入生成器,而本身引发了另一个异常。

TypeError表示self.typestr的实例。从这里我会猜测所涉及的一些代码是误用Failure或者该应用程序使用的是Twisted Spread(误用Failure)。我希望在这里给出的简短答案不是将Twisted Spread和inlineCallbacks结合起来:它们不能很好地协同工作。

由于我在路径中看到了Zenoss,我怀疑你没有写过大部分代码,所以答案对你来说可能没什么帮助......

如果可以,如果Twisted Spread真的涉及到此处,您可以尝试升级Twisted以查看此问题是否消失。我认为这是几年前修复的http://tm.tl/4520的症状(修复首先包含在Twisted 11.1.0中)。

如果不涉及Twisted Spread,则可能需要跟踪误用Failure的其他代码并进行更正。