使用堆栈跟踪创建失败延迟的优雅方法?

Elegant way to create a failed deferred with a stacktrace?

我正在实现一个应该 return 延迟的函数。在该函数中,我确定发生了错误。

我可以提出错误:

raise ValueError("...")

但是函数不再 return 延迟。我不想在调用它时使用 maybeDeferred

或者,我可以 return 像这样延迟:

return defer.fail(Failure(ValueError(...)))

这有效,但 Failure 不会包含堆栈跟踪,因此很难追踪错误。

到目前为止我发现的最好的东西是:

try:
    raise ValueError("...")
except:
    return defer.fail()

我得到了延迟返回并且 Failure 包含堆栈跟踪。但这相当冗长。

有没有更好的方法我想念的?

有点奇怪,这么普通的事情居然没有优雅的解决方案。

这个问题让我有些吃惊,想了想为什么。

如果您只想要带有回溯的失败冒泡并被全局错误处理程序记录下来,则不需要 return defer.fail()。引发异常将获得该行为。

不同的情况是这样的:

foo().addErrback(fooErrorHandler)

在那种情况下,fooErrorHandler 会在延迟的结果失败时被调用,但 不会 当它是同步引发的异常时。那将需要这种更麻烦的形式:

try:
    foo().addErrback(fooErrorHandler)
except Exception, err:
    fooErrorHandler(Failure(err))

诚然,这看起来很糟糕。但是现在我们说的情况是

  1. 您为此调用定义了一个明确的错误处理程序
  2. 错误处理程序对失败的回溯进行处理
  3. 函数可以同步失败异步
  4. 您对同步和异步故障模式使用相同的错误处理程序。

这也许就是为什么它没有像您想象的那样普遍的原因。

当然,它可能不常见的另一个原因是人们通常懒于定义错误处理程序,并且常常懒于记录他们的代码可能引发的异常类型。

啊哈,还有一些事情可能让我更加困惑:Failure 知道如何存储它的堆栈,但它被明确地更改为 not do this unless there's a traceback 出于性能原因。该提交消息描述的获取回溯的方法与 post.

中的四行 try/except 示例相同

我想这可能是 Failure() 的一个选项(因为 captureVars 是),或者一个替代的构造函数方法,如果这确实足以保证它的话。