【问题标题】:How to catch unhandled error in Deferred originating from reactor.stop()如何在 Deferred 中捕获源自 reactor.stop() 的未处理错误
【发布时间】:2014-05-03 23:36:39
【问题描述】:

我是新来的 twisted 并且在使用以下脚本时遇到了问题。

当我运行以下命令时:

#!/usr/bin/env python
from twisted.internet import defer
from twisted.web.client import getPage, reactor

def success(results):
  print 'success'

def error(results):
  print 'error'
  return results

def finished(results):
  print 'finished'
  reactor.stop()

tasks = []

d = getPage('thiswontwork').addCallback(success).addErrback(error)
tasks.append(d)

dl = defer.DeferredList(tasks)
dl.addCallback(finished)

reactor.run()

我得到以下输出:

error
finished
Unhandled error in Deferred:
Unhandled Error
Traceback (most recent call last):
Failure: twisted.internet.error.ConnectionRefusedError: Connection was refused by other side: 61: Connection refused.

我的问题是,当我似乎在错误回调中发现了错误时,为什么会收到未处理的错误?

【问题讨论】:

标签: python asynchronous twisted


【解决方案1】:

问题在于,在您的 error def 中,您返回 result,鉴于它被错误调用,返回是 Failure 对象,并且返回 Failure 对象是 re 的两个标准之一-引发错误状态。请参阅krondo's twisted intro - part 9 的以下简介:

现在,在同步代码中,我们可以使用 raise 关键字“重新引发”异常,而无需任何参数。这样做会引发我们正在处理的原始异常,并允许我们对错误采取一些措施而无需完全处理它。事实证明,我们可以在 errback 中做同样的事情。如果出现以下情况,deferred 将认为回调/errback 失败:

  • 回调/errback 引发任何类型的异常,或
  • 回调/errback 返回一个失败对象。

由于 errback 的第一个参数始终是失败,因此 errback 可以在执行它想要执行的任何操作后通过返回其第一个参数来“重新引发”异常。

是的,刚试过,如果你改变:

def error(results):
  print 'error'
  return results

def error(results):
  print 'error'
  return

您不会重新引发错误状态,因此它不会渗透回反应器,也不会导致让您烦恼的回溯。

附:我不能推荐krondo's twisted introduction!这可能真的很长,但如果你能熬过它,你就真的能够产生扭曲的代码,而这些行为就不会是什么神秘的事情了。

P.P.S 我看到您之前有关于延迟的 SO 问题 (Python DeferredList callback reporting success when deferreds raise error),这可能是您以这种方式构建代码的原因。我认为您可能对 deferreds(尤其是 errbacks)中涉及的 def 的返回值/回调值有一个基本的误解。查看 krondo 的 part 9(尽管您可能需要备份 part 7 或更早的时间才能跟踪它),它确实应该有助于解决问题。

【讨论】:

猜你喜欢
  • 2018-09-04
  • 2012-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多