以下扭曲的代码是否会重新进入问题?

时间:2013-10-22 21:16:09

标签: python twisted deferred

我最近在学习Twisted,刚才我重新阅读了Deferred的一些基本文档,这里有一些示例代码:http://twistedmatrix.com/documents/12.3.0/core/howto/defer.html

如何评论第二个g = Getter()? 是否会重新进入poblem?你对如何避免这类问题有一些好主意吗?

from twisted.internet import reactor, defer

class Getter:
    def gotResults(self, x):
        """
        The Deferred mechanism provides a mechanism to signal error
        conditions.  In this case, odd numbers are bad.

        This function demonstrates a more complex way of starting
        the callback chain by checking for expected results and
        choosing whether to fire the callback or errback chain
        """
        if self.d is None:
            print "Nowhere to put results"
            return

        d = self.d
        self.d = None
        if x % 2 == 0:
            d.callback(x*3)
        else:
            d.errback(ValueError("You used an odd number!"))

    def _toHTML(self, r):
        """
        This function converts r to HTML.

        It is added to the callback chain by getDummyData in
        order to demonstrate how a callback passes its own result
        to the next callback
        """
        return "Result: %s" % r

    def getDummyData(self, x):
        """
        The Deferred mechanism allows for chained callbacks.
        In this example, the output of gotResults is first
        passed through _toHTML on its way to printData.

        Again this function is a dummy, simulating a delayed result
        using callLater, rather than using a real asynchronous
        setup.
        """
        self.d = defer.Deferred()
        # simulate a delayed result by asking the reactor to schedule
        # gotResults in 2 seconds time
        reactor.callLater(2, self.gotResults, x)
        self.d.addCallback(self._toHTML)
        return self.d

def printData(d):
    print d

def printError(failure):
    import sys
    sys.stderr.write(str(failure))

# this series of callbacks and errbacks will print an error message
g = Getter()
d = g.getDummyData(3)
d.addCallback(printData)
d.addErrback(printError)

# this series of callbacks and errbacks will print "Result: 12"
#g = Getter() #<= What about commenting this line out? 
d = g.getDummyData(4)
d.addCallback(printData)
d.addErrback(printError)

reactor.callLater(4, reactor.stop)
reactor.run()

1 个答案:

答案 0 :(得分:1)

是的,如果您评论第二个g = Getter(),则会出现问题。相同的Deferred将触发两次,因为Deferred对象中存储了Getter。特别是,对getDummyData的第二次调用将覆盖第一个Deferred

你不应该这样做。总的来说,我认为持有Deferred个对象并不是一个好主意,因为它们只能触发一次并且很容易出现像你这样的问题。

你应该做的是:

def getDummyData(self, x):
    ...
    d = defer.Deferred()
    # simulate a delayed result by asking the reactor to schedule
    # gotResults in 2 seconds time
    reactor.callLater(2, self.gotResults, x, d)
    d.addCallback(self._toHTML)
    return d

并且:

def gotResults(self, x, d):
    """
    The Deferred mechanism provides a mechanism to signal error
    conditions.  In this case, odd numbers are bad.

    This function demonstrates a more complex way of starting
    the callback chain by checking for expected results and
    choosing whether to fire the callback or errback chain
    """
    if d is None:
        print "Nowhere to put results"
        return

    if x % 2 == 0:
        d.callback(x*3)
    else:
        d.errback(ValueError("You used an odd number!"))

请注意,在这种情况下Getter没有状态,这很好,而且你不需要一个类!

我的意见是Deferred s应该用来让你的函数的调用者能够在结果可用时对结果做一些事情。他们应该用于任何发烧友。所以,我总是有

def func():
    d = defer.Deferred()
    ...
    return d

如果来电者因任何原因必须抓住Deferred,他们可以,但我可以多次免费拨打func,而不必担心隐藏状态。