本文和大家分享的是在使用python
進行數(shù)據(jù)抓取中,異常重試相關解決辦法,一起來看看吧,希望對大家
學習python有所幫助。
在做數(shù)據(jù)抓取的時候,經(jīng)常遇到由于網(wǎng)絡問題導致的程序保存,先前只是記錄了錯誤內(nèi)容,并對錯誤內(nèi)容進行后期處理。
原先的流程:
defcrawl_page(url):
pass
deflog_error(url):
pass
url = ""
try:
crawl_page(url)
except:
log_error(url)
改進后的流程:
attempts = 0
success =
Falsewhile attempts < 3
and
not success:
try:
crawl_page(url)
success =
True
except:
attempts += 1
if attempts == 3:
break
最近發(fā)現(xiàn)的新的解決方案:retrying
retrying
是一個
Python
的重試包,可以用來自動重試一些可能運行失敗的程序段。
retrying
提供一個裝飾器函數(shù)
retry
,被裝飾的函數(shù)就會在運行失敗的條件下重新執(zhí)行,默認只要一直報錯就會不斷重試。
importrandom
fromretryingimportretry
@retry
defdo_something_unreliable():
if random.randint(0, 10) > 1:
raiseIOError("Broken sauce, everything is hosed!!!111one")
else:
return "Awesome sauce!"
printdo_something_unreliable()
如果我們運行have_a_try
函數(shù),那么直到
random.randint
返回
5
,它才會執(zhí)行結(jié)束,否則會一直重新執(zhí)行。
retry
還可以接受一些參數(shù),這個從源碼中
Retrying
類的初始化函數(shù)可以看到可選的參數(shù):
· stop_max_attempt_number
:用來設定最大的嘗試次數(shù),超過該次數(shù)就停止重試
· stop_max_delay
:比如設置成
10000
,那么從被裝飾的函數(shù)開始執(zhí)行的時間點開始,到函數(shù)成功運行結(jié)束或者失敗報錯中止的時間點,只要這段時間超過
10
秒,函數(shù)就不會再執(zhí)行了
· wait_fixed
:設置在兩次
retrying
之間的停留時間
· wait_random_min
和
wait_random_max
:用隨機的方式產(chǎn)生兩次
retrying
之間的停留時間
· wait_exponential_multiplier
和
wait_exponential_max
:以指數(shù)的形式產(chǎn)生兩次
retrying
之間的停留時間,產(chǎn)生的值為
2^previous_attempt_number * wait_exponential_multiplier
,
previous_attempt_number
是前面已經(jīng)
retry
的次數(shù),如果產(chǎn)生的這個值超過了
wait_exponential_max
的大小,那么之后兩個
retrying
之間的停留值都為
wait_exponential_max
。這個設計迎合了
exponential backoff
算法,可以減輕阻塞的情況。
·
我們可以指定要在出現(xiàn)哪些異常的時候再去
retry
,這個要用
retry_on_exception
傳入一個函數(shù)對象:
defretry_if_io_error(exception):
return isinstance(exception, IOError)
@retry(retry_on_exception=retry_if_io_error)
defread_a_file():
withopen("file", "r")
as f:
return f.read()
在執(zhí)行read_a_file
函數(shù)的過程中,如果報出異常,那么這個異常會以形參
exception
傳入
retry_if_io_error
函數(shù)中,如果
exception
是
IOError
那么就進行
retry
,如果不是就停止運行并拋出異常。
我們還可以指定要在得到哪些結(jié)果的時候去retry
,這個要用
retry_on_result
傳入一個函數(shù)對象:
defretry_if_result_none(result):
return resultis None
@retry(retry_on_result=retry_if_result_none)
defget_result():
return None
在執(zhí)行get_result
成功后,會將函數(shù)的返回值通過形參
result
的形式傳入
retry_if_result_none
函數(shù)中,如果返回值是
None
那么就進行
retry
,否則就結(jié)束并返回函數(shù)值。
來源:
標點符