logo

Wednesday 23rd of May 2012

廣告

廣告贊助商

首頁 Python教學 Twisted教學 Deferred應用的實例 : retry
Deferred應用的實例 : retry PDF 列印 E-mail
作者是 Victor   
週三, 11 二月 2009 21:10

為什麼需要Retry

因為網路連線並不是百分之一百一定成功的,很多時候都會遇到斷線、伺服器忙錄中等等狀況,當我在寫截取網頁資料時就遇到這樣的問題,這個時候就需要有重試的機制,最簡單的方法就是,替每個可能出錯的網路連線的非同步函數都寫一個可重試的版本,那會是一場惡夢,我為了解決這樣的問題,就考慮到Deferred本身的特性,讓它可以套用在任何其它回傳Deferred物件的函數身上,封裝其它函數時可以增加你需要的功能進去,但是又保持對外界的一致性

程式碼

import logging

from twisted.internet import defer

log = logging.getLogger('retry')

def retry(times, func, *args, **kwargs):
    """retry a defer function
    
    @param times: how many times to retry
    @param func: defer function
    """
    errorList = []
    deferred = defer.Deferred()
    def run():
        log.info('Try %s(*%s, **%s)', func.__name__, args, kwargs)
        d = func(*args, **kwargs)
        d.addCallbacks(deferred.callback, error)
    def error(error):
        errorList.append(error)
        # Retry
        if len(errorList) < times:
            log.info('Failed to try %s(*%s, **%s) %d times, retry...', func.__name__, args, kwargs, len(errorList))
            run()
        # Fail
        else:
            log.info('Failed to try %s(*%s, **%s) over %d times, stop', func.__name__, args, kwargs, len(errorList))
            deferred.errback(errorList)
    run()
    return deferred

有了這樣的機制,我們可以輕鬆地將它與任何defer函數串在一起,以下是和getPage一起使用的範例

from twisted.internet import reactor
from twisted.web.client import getPage

def output(data):
    print 'output', data
    
def error(error):
    print 'finall error', error

d = retry(3, getPage, 'http://www.google2.com')
d.addCallbacks(output, error)

d = retry(3, getPage, 'http://www.google.com')
d.addCallbacks(output, error)

reactor.run()

你不必更改你現有的任何程式碼,只要將這個函數套用在你想retry的函數上,它就會自行重試,就就是Deferred機制帶來的彈性

 

核心是 Joomla!. Designed by: Free Joomla Theme, whois protect. Valid XHTML and CSS.