2013-06-24 43 views
1

我創建一個程序,使用Twisted模塊和回調。 但是,我一直有問題,因爲異步部分破壞。有條件的如果在異步python程序與扭曲

我已經學會了(也由以前的問題..)的回調將在某一個點來執行,但是這是不可預測的。

不過,我有一定的程序是這樣

j = calc(a) 
i = calc2(b) 
f = calc3(c) 

if s: 
    combine(i, j, f) 

現在布爾s是由calc3做了回調設置。顯然,這會導致未定義的錯誤,因爲在需要s之前不會執行回調。 但是,我不確定如果使用Twisted的異步編程語句如何執行SHOULD。我一直在嘗試很多不同的東西,但找不到任何有效的東西。

有什麼方法可以使用需要回調值的條件?

而且,我使用VIFF的安全計算(使用雙絞線):VIFF

+0

是'calc','calc2','calc3'神奇的VIFF東西嗎?還是他們正常的功能,每個返回一個延期?如果他們是不可思議的VIFF事物,您是否可以擴展您的問題以包含他們的定義? –

+0

所有功能都是「普通」功能,沒有'VIFF'的東西。除了'calc3'包含共享(被緩存的類型)和回調。 – Mythio

回答

2

你要找也許什麼是twisted.internet.defer.gatherResults

d = gatherResults([calc(a), calc2(b), calc3(c)]) 
def calculated((j, i, f)): 
    if s: 
     return combine(i, j, f) 
d.addCallback(calculated) 

然而,這仍然有s是不確定的問題。我無法確定您期望s的定義。如果它是calc3中的局部變量,那麼您需要將其返回,以便調用者可以使用它。

也許CALC3看起來是這樣的:

def calc3(argument): 
    s = bool(argument % 2) 
    return argument + 1 

所以,相反,考慮使它看起來像這樣:

Calc3Result = namedtuple("Calc3Result", "condition value") 

def calc3(argument): 
    s = bool(argument % 2) 
    return Calc3Result(s, argument + 1) 

現在你可以重寫調用代碼,所以它的實際工作:

這是不清楚你在這裏問什麼。這聽起來像你知道什麼是回調,但如果是這樣,那麼你應該能夠在這個回答自己到達:

d = gatherResults([calc(a), calc2(b), calc3(c)]) 
def calculated((j, i, calc3result)): 
    if calc3result.condition: 
     return combine(i, j, calc3result.value) 
d.addCallback(calculated) 

或者,根據您在下面的評論,也許calc3看起來更像這個(這是最後想我會做,如果它是錯的,你想了解更多的輸入,然後請實際上份額calc3定義):

def _calc3Result(result, argument): 
    if result == "250": 
     # SMTP Success response, yay 
     return Calc3Result(True, argument) 
    # Anything else is bad 
    return Calc3Result(False, argument) 

def calc3(argument): 
    d = emailObserver("The argument was %s" % (argument,)) 
    d.addCallback(_calc3Result) 
    return d 

幸運的是,calc3這個定義將工作只是罰款gatherResults/calculated上面的代碼塊。

+0

我對此表示贊同。我之前從未遇到過gatherResults。所以對我來說還有一些新東西 – jbreicis

+0

布爾's'是由'calc3'完成回調的延遲定義的。所以在設置布爾值之前,需要知道延遲的值,這是問題所在。 – Mythio

+0

使用這個答案的一些想法,我設法解決回調的問題。 – Mythio

0

你必須把if回調。您可以使用Deferred來構建您的回調。

0

正如在前面的回答說 - 在preocessing邏輯應該在回調鏈來處理,下面是簡單的代碼演示這是怎麼工作的。 C{DelayedTask}是未來發生的任務的虛擬實現,並且提供延遲的火災。

所以我們首先構造一個特殊的對象 - C{ConditionalTask}它負責storring的多個結果和服務回調。

CALC1,CALC2和CALC3返回deferreds,它有自己的回調指出C{ConditionalTask}.x_callback

每個C{ConditionalTask}.x_callback都會打電話給C{ConditionalTask}.process,它會檢查是否所有結果都已經註冊並在整套設備上觸發。

另外 - C{ConditionalTask}.c_callback設置的wheather與否的數據,應當在所有被處理的標誌。

from twisted.internet import reactor, defer 

class DelayedTask(object): 
    """ 
    Delayed async task dummy implementation 
    """ 
    def __init__(self,delay,deferred,retVal): 
     self.deferred = deferred 
     self.retVal = retVal 
     reactor.callLater(delay, self.on_completed) 
    def on_completed(self): 
     self.deferred.callback(self.retVal) 


class ConditionalTask(object): 
    def __init__(self): 
     self.resultA=None 
     self.resultB=None 
     self.resultC=None 
     self.should_process=False 

    def a_callback(self,result): 
     self.resultA = result 
     self.process() 

    def b_callback(self,result): 
     self.resultB=result 
     self.process() 

    def c_callback(self,result): 
     self.resultC=result 
     """ 
     Here is an abstraction for your "s" boolean flag, obviously the logic 
     normally would go further than just setting the flag, you could 
     inspect the result variable and do other strange stuff 
     """ 
     self.should_process = True 
     self.process() 

    def process(self): 
     if None not in (self.resultA,self.resultB,self.resultC): 
      if self.should_process: 
       print 'We will now call the processor function and stop reactor' 
       reactor.stop() 



def calc(a): 
    deferred = defer.Deferred() 
    DelayedTask(5,deferred,a) 
    return deferred 

def calc2(a): 
    deferred = defer.Deferred() 
    DelayedTask(5,deferred,a*2) 
    return deferred 

def calc3(a): 
    deferred = defer.Deferred() 
    DelayedTask(5,deferred,a*3) 
    return deferred 

def main(): 
    conditional_task = ConditionalTask() 
    dFA = calc(1) 
    dFB = calc2(2) 
    dFC = calc3(3) 

    dFA.addCallback(conditional_task.a_callback) 
    dFB.addCallback(conditional_task.b_callback) 
    dFC.addCallback(conditional_task.c_callback) 

    reactor.run() 
+0

這不是非常習慣的扭曲使用的代碼。 :/ –

+0

不,它不是慣用的扭曲代碼。它服務於完全不同的目的 - 允許解釋過分簡化的異步思想。結果並加入多個異步結果。我沒有開始將他推向DeferredList和鏈接延期/堆疊以簡化解決方案。你和@ glyph現在都被允許向我灌注熱熔岩。 – jbreicis

+0

我還做了__assumption__ calc,calc2和calc3是可以同時調用的獨立函數調用。 – jbreicis