在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Python/ 增強defer功能的客戶端
小插曲 Deferred
異步編程模式與Reactor初探
使用Deferred新功能實現(xiàn)新客戶端
由twisted支持的客戶端
增強defer功能的客戶端
改進詩歌下載服務器
測試詩歌
更加"抽象"的運用Twisted
Deferred用于同步環(huán)境
輪子內的輪子: Twisted和Erlang
Twisted 進程守護
構造"回調"的另一種方法
Twisted 理論基礎
惰性不是遲緩: Twisted和Haskell
第二個小插曲,deferred
使用Deferred的詩歌下載客戶端
Deferreds 全貌
結束
取消之前的意圖
由Twisted扶持的客戶端
改進詩歌下載服務器
初識Twisted

增強defer功能的客戶端

版本5.0

現(xiàn)在我們將要向詩歌下載客戶端添加一些新的處理邏輯,包括在第九部分提到要添加的功能。不過,首先我要說明一點:我并不知道如何實現(xiàn)Byronification引擎。那超出了我的編程能力范圍。取而代之的,我想實現(xiàn)一個簡單的功能,即Cummingsifier。其只是將詩歌內容轉換成小寫字母:

def cummingsify(poem)
    return poem.lower()

這個方法如此之簡單以至于它永遠不會出錯。版本5.0的實現(xiàn)代碼在twisted-client-5/get-poetry.py文件中。我們使用了修改后的 cummingsify,其會隨機地選擇以下行為:

  1. 返回詩歌的小寫版本
  2. 拋出一個GibberishError異常
  3. 拋出一個ValueError

這樣,我們便模擬出來一個會因為各種意料不到的問題而執(zhí)行失敗的復雜算法。其它部分的僅有的改變在方法poetry_main中:

def poetry_main():
    addresses = parse_args()
    from twisted.internet import reactor
    poems = []
    errors = []
    def try_to_cummingsify(poem):
        try:
            return cummingsify(poem)
        except GibberishError:
            raise
        except:
            print 'Cummingsify failed!'
            return poem
    def got_poem(poem):
        print poem
        poems.append(poem)
    def poem_failed(err):
        print >>sys.stderr, 'The poem download failed.'
        errors.append(err)
    def poem_done(_):
        if len(poems) + len(errors) == len(addresses):
            reactor.stop()
    for address in addresses:
        host, port = address
        d = get_poetry(host, port)
        d.addCallback(try_to_cummingsify)
        d.addCallbacks(got_poem, poem_failed)
        d.addBoth(poem_done)
    reactor.run()

因此,當從服務器上下載一首詩歌時,可能會出現(xiàn)如下情況:

  1. 打印詩歌的小寫版本
  2. 打印"Cummingsify failed"并附上原始形式的詩歌
  3. 打印"The poem download failed"。

為了實現(xiàn)下面內容的效果,你可以打開多個服務器或打開一個服務器多次,直到你觀察到所有不同的結果,當然也嘗試一下去連接一個沒有服務器值守的端口。

圖19是我們給deferred添加回調后形成的callback/errback鏈:

http://wiki.jikexueyuan.com/project/twisted-intro/images/p10_deferred-42.png" alt="" />

注意到,"pass-throug"errback通過addCallback添加到鏈中。它會將任何其接收到的Failure傳遞給下一個errback(即poem_failed函數(shù))。因此poem_failed函數(shù)可以處理來自get_poetry與try_to_commingsify兩者的failure。下面讓我們來分析下deferred可能會出現(xiàn)的激活情況,圖20說明了我們能夠下載到詩歌并且try_to_commingsify成功執(zhí)行的路線圖:

http://wiki.jikexueyuan.com/project/twisted-intro/images/p10_deferred-5.png" alt="" />

在這種情況中,沒有回調執(zhí)行失敗,因此控制權一直在callback中流動。注意到poem_done收到的結果是None,這是因為它并沒有返回任何值。如果我們想讓后續(xù)的回調都能觸及到詩歌內容,只要顯式地讓got_poem返回詩歌即可。

圖21說明了我們在成功下載到詩歌后,但在try_to_cummingsify中拋出了GibberishError:

http://wiki.jikexueyuan.com/project/twisted-intro/images/p10_deferred-6.png" alt="" />

由于try_to_cummingsify回調拋出了GibberishError,所以控制權轉移到了errback鏈,即poem_fail回調被調用并傳入的捕獲的異常作為其參數(shù)。

由于poem_failed并沒有拋出獲異?;蚍祷匾粋€Failure,因此在它執(zhí)行完后,控制權又回到了callback鏈中。如果我們想讓poem_fail完全處理好傳進來的錯誤,那么返回一個None是再好不過的做法了。相反,如果我們只想讓poem_failed采取一部分行動,但繼續(xù)傳遞這個錯誤,那么我們需要改寫poem_failed,即將參數(shù)err作為返回值返回。如此一來,控制權交給了下一個errback回調。

注意到,迄今為止,got_poem與poem_failed都不可能出現(xiàn)執(zhí)行失敗的情況,因此errback鏈上的poem_done是不可能被激活的。但在任何情況下這樣做都是安全的,這體現(xiàn)了"防御式"編程的思想。比如在got_poem或poem_failed出現(xiàn)了bugs,那么這樣做就不會讓這些bugs的影響進入Twisted的核心代碼區(qū)。鑒于上面的描述,可以看出addBoth類似于try/except中的finally語句。

下面我們再來看看第三種可能情況,即成功下載到詩歌但try_to_cummingsify拋出了VauleError,如圖22:

http://wiki.jikexueyuan.com/project/twisted-intro/images/p10_deferred-7.png" alt="" />

除了got_poem得到是原始式樣的詩歌而不是小寫版的外,與圖20描述的情況完全相同。當然,控制權還是在try_to_cummingsif中進行了轉移,即使用了try/except捕獲了ValueError并返回了原始式樣的詩歌。而這一切deferred并不知曉。

最后,我們來看看當試圖連接一個無服務器值守的端口會出現(xiàn)什么情況,如圖23所示:

http://wiki.jikexueyuan.com/project/twisted-intro/images/p10_deferred-8.png" alt="" />

由于poem_failed返回了一個None,因此控權又回到了callback鏈中。

版本5.1

在版本5.0中我們使用普通的try/except來捕獲try_to_cummingsify中的異常,而沒有讓deferred來捕獲這個異常。這其實并沒有什么錯誤,但下面我們將采取一種新的方式來處理異常。

設想一下,我們讓deferred來捕獲 GibberishError 與ValueError 異常,并將其傳遞到errback鏈中進行處理。如果要保留原有的行為,那么需要下面的errback來判斷錯誤類型是否為Valuerror,如果是,那么返回原始式樣的詩歌,這樣一來,控制權再次回到callback鏈中并將原始式樣的詩歌打印出來。

但有一個問題:errback并不會得到原始詩歌內容 。它只會得到由cummingsify拋出的vauleError異常。為了讓errback處理這個錯誤,我們需要重新設計它來接收到原始式樣的詩歌。

一種方法是改變cummingsify以讓異常信息中包含原始式樣的詩歌。這也正是我們在5.1版本中做的,其代碼實現(xiàn)在twisted-client-5/get-poetry-1.py中。我們改寫ValueError異常為CannotCummingsify異常,其能將詩歌作為其第一個參數(shù)來傳遞。

如果cummingsify是外部模塊中一個真實存在的函數(shù),那么其最好是通過另一個函數(shù)來捕獲非GibberishError并拋出一個CannotCummingsify異常。這樣,我們的poetry_main就成為:

def poetry_main():
    addresses = parse_args()
    from twisted.internet import reactor
    poems = []
    errors = []
    def cummingsify_failed(err):
        if err.check(CannotCummingsify):
            print 'Cummingsify failed!'
            return err.value.args[0]
        return err
    def got_poem(poem):
        print poem
        poems.append(poem)
    def poem_failed(err):
        print >>sys.stderr, 'The poem download failed.'
        errors.append(err)
    def poem_done(_):
        if len(poems) + len(errors) == len(addresses):
            reactor.stop()
    for address in addresses:
        host, port = address
        d = get_poetry(host, port)
        d.addCallback(cummingsify)
        d.addErrback(cummingsify_failed)
        d.addCallbacks(got_poem, poem_failed)
        d.addBoth(poem_done)

而新的deferred結構如圖24所示:

http://wiki.jikexueyuan.com/project/twisted-intro/images/p10_deferred-9.png" alt="" />

來看看cummingsify_failed的errback回調:

def cummingsify_failed(err):
    if err.check(CannotCummingsify):
        print 'Cummingsify failed!'
        return err.value.args[0]
    return err

我們使用了Failure中的check方法來確認嵌入在Failure中的異常是否是CannotCummingsify的實例。如果是,我們返回異常的第一個參數(shù)(即原始式樣詩歌)。因此,這樣一來返回值就不是一個Failure了,控制權也就又回到callback鏈中了。否則(即異常不是CannotCummingsify的實例),我們返回一個Failure,即將錯誤傳遞到下一個errback中。

圖25說明了當我們捕獲一個CannotCummingsify時的調用過程:

http://wiki.jikexueyuan.com/project/twisted-intro/images/p10_deferred-10.png" alt="" />

因此,當我們使用deferrd時,可以選擇使用try/except來捕獲異常,也可以讓deferred來將異常傳遞到errback回調鏈中進行處理。

總結

在這個部分,我們增強了客戶端的Deferred的功能,實現(xiàn)了異常與結果在callback/errback鏈中"路由"。(你可以將各個回調看作成路由器,然后根據(jù)傳入?yún)?shù)的情況來決定其返回值進入下一個stage的哪條鏈,或者說控制權進入下一個stage的哪個類型的回調)。雖然示例程序是虛構出來的,但它揭示了控制權在deferred的回調鏈中交錯傳遞具體方向依賴于返回值的類型。

那我們是不是已經對deferred無所不知了?不,我們還會在下面的部分繼續(xù)講解deferred的更多的功能。但在第十一部分,我們先不講這部分內容,而是實現(xiàn)我們的Twisted版本的詩歌下載服務器。

參考

本部分原作參見: dave @ http://krondo.com/?p=1956

本部分翻譯內容參見楊曉偉的博客 http://blog.sina.com.cn/s/blog_704b6af70100q87q.html