Twisted 如何摆脱 Deferred 中未处理的错误?

Twisted how to get rid of Unhandled error in Deferred?

我有一个 deferredList 会在第一个回调时触发,但我实际上是在玩回调链的性质,所以如果没有触发任何回调,则会触发 errbacks。

问题是一旦我添加了 errbacks 的处理程序,addErrback 和我创建的 Failure,触发器和 stdout 仍然对我大喊大叫以下:

Unhandled error in Deferred:

Traceback (most recent call last):
Failure: __main__.notFound: Match not found!

最后的 errback 执行以下操作:

def emptyQuery(error, name):
    errorType = error.trap(notFound)
    if errorType == notFound:
        print("[-] Item not found in given sources: {name}".format(name=name))
    print("->", errorType)
    return

因此,

[(False, <twisted.python.failure.Failure __main__.notFound: Match not found!>)]
[-] Item not found for current sources: GIA-S12
-> <class '__main__.notFound'>
Unhandled error in Deferred:

Traceback (most recent call last):
Failure: __main__.notFound: Match not found!

我怎样才能摆脱那个“未处理的东西”?我陷入了错误,我不知道它为什么这样喊我。

它实际上是由我实现的这个for循环触发的:

for item in items:
        name, price = item
        itemQuery_deferreds = []
        for urlObject in URLS:
            urlFire = poolsem.acquire().addCallback(initQuery, urlObject.url, name, googleClient)
            itemQuery_deferreds.append(urlFire)
        itemQuery = DeferredList(itemQuery_deferreds, fireOnOneCallback=True)
        itemQuery.addCallback(parseData)
        itemQuery.addErrback(emptyQuery, name)

当然,在转到 errback 处理程序 emptyQuery 之前,我必须先期待回调被调用:

def parseData(data):
    print(data)
    for code, status in data:
        if not code:
            return status
        else:
            store = status

另外,每个 我所有代码中的延迟都包含一个错误返回处理程序:

def onError(error):
    return error

注意:我发现这很难调试,如果您需要更多信息,请询问。

consumeErrors=True 传递给您的 DeferredList 构造。

您正在使用像这样创建的 Deferreds 填充 DeferredList

urlFire = poolsem.acquire().addCallback(initQuery, urlObject.url, name, googleClient)

如果 urlFire 曾经失败,那么 DeferredList 会观察到此失败并使其在自己的结果中可用。如果你没有通过 consumeErrors=True 那么 DeferredList 确保 urlFire 保持它的失败结果。如果您确实通过了 consumeErrors=True,那么 DeferredList 会将其元素上的任何失败变成 None.

ALSO, every Deferred that I have in all my code contains an errback handler:

def onError(error):
   return error

这没有意义。这个 onError errback 是一个 no-op。它接受一个错误然后传播它。 dd.addErrback(onError) 的行为方式完全相同。如果你想摆脱错误,你必须 而不是 re-raise 它或 return 它。

DeferredList(consumeErrors=True) 有效地做的是让 DeferredList 添加一个 errback,如:

def onError(reason):
    return None

每个延迟。 不想对你所做的每个 urlFire 延迟执行此操作的原因是它等同于“除了:通过”。它将抑制来自那些 Deferred 的所有错误。这甚至会阻止 DeferredList 对它们做任何事情。 DeferredList(consumeErrors=True) 确保错误传播到 其他地方 因此可以在单个 Deferred 上抑制它们。