3

結果を発生させる遅延があります。この結果を、それを消費するいくつかの関数に渡したいと思います。これを行う簡単な方法は、遅延オブジェクトにコールバックを追加することです。ただし、関数の 1 つがたまたま同じ結果を返さない場合、後で追加された関数は別の結果を取得しますが、これは望ましくありません。この問題を解決するには、次のことを行う必要がありました。

def branchDeferred(d):
    #return a deferred which returns d's results without affecting them
    branchD = defer.Deferred()
    def success(result):
        branchD.callback(result)
        return result
    def failure(fail):
        branchD.errback(fail)
        return fail
    d.addCallbacks(success, failure)
    return branchD

違いを観察します。

>>> resultD = defer.Deferred()
>>> resultD.addCallback(printCallback)
<Deferred at 0x2a3bcb0>
>>> resultD.addCallback(printCallback)
<Deferred at 0x2a3bcb0>
>>> resultD.callback("lovely")
Result: lovely
Result: None

対:

>>> resultD = defer.Deferred()
>>> branchDeferred(resultD).addCallback(printCallback)
<Deferred at 0x2a2ada0>
>>> branchDeferred(resultD).addCallback(printCallback)
<Deferred at 0x2b658a0>
>>> resultD.callback("lovely")
Result: lovely
Result: lovely

組み込みのツイストイディオムを使用してこれを行うより良い方法はありますか? それとも、これが唯一の方法ですか?

ご参考までに、これはdefer.inlineCallbacks、継承された遅延の結果を伝播する代わりに消費する which を使用していたために発生しました。

編集:このコードは、私が話していることを示しています:

>>> class Baz:
        def __init__(self):
            self.resultD = defer.Deferred()

        @defer.inlineCallbacks
        def fooMe(self, name):
            result = yield self.resultD
            print "fooMe(%s) got: %s" % (name, result,)
            defer.returnValue(result)


>>> b = Baz()
>>> d1 = b.fooMe("one")
>>> d2 = b.fooMe("two")
>>> b.resultD.callback("SHINIES")
fooMe(one) got: SHINIES
fooMe(two) got: None

のこのコードが_inlineCallbacks()原因twisted/internet/defer.pyです:

        def gotResult(r):
            if waiting[0]:
                waiting[0] = False
                waiting[1] = r
            else:
                _inlineCallbacks(r, g, deferred)

        result.addBoth(gotResult)

gotResult最後にはしませんreturn r。ねじれたインストールにパッチを当ててこれを機能させたくないので、回避策を行うためのよりクリーンな方法があるかどうか疑問に思っていました。

4

0 に答える 0