【问题标题】:python twisted DeferedList ErrorBack ( Unhandled error in Deferred )python twisted DeferedList ErrorBack(Deferred 中未处理的错误)
【发布时间】:2011-01-11 19:19:27
【问题描述】:

在下面的代码中,我传递了一个主机:端口组合,并尝试使用扭曲延迟从服务器获取一些信息。我已经展示了我正在尝试做的一个非常基本的代码。与主机端口的连接是通过 httplib 建立的。如果主机启动,它可以正常工作。调用正确的回调方法。但是当它失败时(当检索 url 失败时),它不会进入 printError 函数。我收到“延迟中的未处理错误”错误并且循环停止。有人可以告诉我如何摆脱错误。请提供解决方案。

import httplib, time, sys

from twisted.internet import reactor, defer, task

from twisted.python import log

class Getter:

    def gotResults(self, x):

        ( host, port ) = x.split(":")
        conn = httplib.HTTPConnection( host, port )

        try :
            conn.request ( 'GET', '/get/data/' )
            response = conn.getresponse()
            self.d.callback ( response )
        except ( httplib.HTTPException ) :
            self.d.errback(ValueError("Error Connecting"))



    def getDummyData(self, x):
        currTime = time.strftime( "%H:%M:%S" )
        print currTime
        self.d = defer.Deferred()
        self.gotResults(x)
        return self.d



def printData(data):

    for d in data:
        print "Results %s %s" % ( str(d[1].status), str(d[1].reason)  )

def printError(data):

    print data



def testmessage():
# this series of callbacks and errbacks will print an error message
    g = Getter()
    deferred1 = g.getDummyData( 'valid_hostname1:port1' )
    # this should go to printData

    g = Getter()
    deferred2 = g.getDummyData('invalid_hostname2:port2')
    # this should go to printError

    d1 = defer.DeferredList ( [ deferred1, deferred2 ] )
    d1.addCallback ( printData )
    d1.addErrback  ( printError )



x = task.LoopingCall ( testmessage )
x.start ( 1 )
reactor.callLater(300, reactor.stop);
reactor.run()

【问题讨论】:

  • 除了您对 Deferreds 的问题之外,您可能还想使用 twisted.web.client 而不是 httplib

标签: python twisted deferred


【解决方案1】:

问题是您假设conn.request(在您的第 17 行)会引发 httplib.HTTPException,但这不是它引发的异常类型。由于您不太确定它会引发什么异常,我建议您创建一个笼统的except... 声明并从sys.exc_info() 获取异常数据。

按照以下方式修复它:

import httplib, time, sys

from twisted.internet import reactor, defer, task

from twisted.python import log

class Getter:

    def gotResults(self, x):

        ( host, port ) = x.split(":")
        conn = httplib.HTTPConnection( host, port )

        try :
            conn.request ( 'GET', '/get/data/' )
            response = conn.getresponse()
            self.d.callback ( response )
        except:
            self.d.errback(sys.exc_info())


    def getDummyData(self, x):
        currTime = time.strftime( "%H:%M:%S" )
        print currTime
        self.d = defer.Deferred()
        self.gotResults(x)
        return self.d



def printData(data):

    for d in data:
        print "Results %s %s" % ( str(d[1].status), str(d[1].reason)  )

def printError(data):

    print data



def testmessage():
# this series of callbacks and errbacks will print an error message
    g = Getter()
    deferred1 = g.getDummyData( 'valid_hostname1:port1' )
    # this should go to printData

    g = Getter()
    deferred2 = g.getDummyData('invalid_hostname2:port2')
    # this should go to printError

    d1 = defer.DeferredList ( [ deferred1, deferred2 ] )
    d1.addCallback ( printData )
    d1.addErrback  ( printError )



x = task.LoopingCall ( testmessage )
x.start ( 1 )
reactor.callLater(300, reactor.stop);
reactor.run()

【讨论】:

  • 您可以在 except 正文中执行 self.d.errback() ,无论有什么异常,Deferred 都会弄清楚并将其发送到 errback 链。
  • 非常感谢。它有效,但似乎进入了 printData(即使对于失败的对象)而不是 printError。就我而言,这解决了大部分问题,因为我可以解决它,但如果您也可以发布解决方案,那就太好了。
  • DeferredList(list) 永远不会触发 errback,只会触发回调。如果你想从它那里得到一个 errback,你可能想要fireOnOneErrback 标志。您可能还需要gatherResults 而不是DeferredList。这主要取决于您希望如何处理多个故障。
猜你喜欢
  • 1970-01-01
  • 2017-10-31
  • 1970-01-01
  • 2020-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-04
  • 1970-01-01
相关资源
最近更新 更多