How to catch unhandled error in Deferred originating from reactor.stop()

余生长醉 提交于 2019-12-10 22:45:21

问题


I am new to twisted and having trouble with the following script.

When I run the following:

#!/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()

I get the following output:

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.

My question is why am I getting an unhandled error when I seem to have caught the error with my error callback?


回答1:


The problem is that in your error def you return result which, given it was called by an error back is a Failure object, and returning a Failure object is one of the two criteria for re-raising the error state. See the following blurb from krondo's twisted intro - part 9:

Now, in synchronous code we can “re-raise” an exception using the raise keyword without any arguments. Doing so raises the original exception we were handling and allows us to take some action on an error without completely handling it. It turns out we can do the same thing in an errback. A deferred will consider a callback/errback to have failed if:

  • The callback/errback raises any kind of exception, or
  • The callback/errback returns a Failure object.

Since an errback’s first argument is always a Failure, an errback can “re-raise” the exception by returning its first argument, after performing whatever action it wants to take.

Yup, just tried it, if you change:

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

to

def error(results):
  print 'error'
  return

You won't re-raise the error state, so it won't percolate back to the reactor, and won't cause the traceback thats annoying you.

P.S. I can't recommend krondo's twisted introduction enough! It may be really long but if you can get through it, you really will be able to produce code in twisted and these sort of behaviors won't be a mystery.

P.P.S I see you have previous SO question (Python DeferredList callback reporting success when deferreds raise error) about deferred's that might be the reason you built the code this way. I think you may have a fundamental misunderstanding about the return-value/callback-value of def's involved in deferreds (particularly errbacks). Check out part 9 (though you might have to backup part 7 or even earlier to track it) of krondo's, it really should help clear things up.



来源:https://stackoverflow.com/questions/23450952/how-to-catch-unhandled-error-in-deferred-originating-from-reactor-stop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!