Wednesday 23rd of May 2012
廣告
| Deferred應用的實例 : retry |
|
|
|
| 作者是 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.


