呼叫外部 API 時常遇到網路抖動導致暫時性失敗。寫一個通用裝飾器,自動重試指定次數,提升系統健壯性。
# -*- coding: utf-8 -*-
def conn_try_again(func):
RETRIES = 2
state = {'count': 0}
def wrapped(*args, **kwargs):
try:
return func(*args, **kwargs)
except Exception as err:
if state['count'] < RETRIES:
state['count'] += 1
return wrapped(*args, **kwargs)
raise
return wrapped
使用 dict 封裝計數器以繞過 Python 2 非區域變數限制;Python 3 可直接用 nonlocal。
@conn_try_again
def post_query_bandwidth(contract_no, data_month, product_code):
import urllib, urllib2
post_data = {'contract': contract_no, 'month': data_month, 'code': product_code}
params = urllib.urlencode(post_data)
response = urllib2.urlopen(API_URL + '?' + params)
data = response.read()
return data if data else {}
若 try 區塊拋出例外,裝飾器會自動重試最多 2 次;仍失敗則向上拋出原始例外。
time.sleep(2 ** attempt))。urllib2.URLError, socket.timeout)。tenacity 或 requests + urllib3.Retry。