[英]Retry loading page on timeout with urllib2?
我在遇到超時錯誤時試圖強制Python重新嘗試加載頁面。 有沒有一種方法可以讓我重試特定的次數(可能在特定的時間延遲之后)?
任何幫助,將不勝感激。
謝謝。
urllib2
沒有內置任何功能,但是您可以自己編寫。
棘手的是,如urlopen
文檔所說,無論出什么問題,您都只會收到URLError
。 那么,您怎么知道是超時還是其他?
好吧,如果您查詢URLError
,它說這會有一個reason
,這將是遠程URL的socket.error
。 而且,如果您查找socket.error
它會告訴您它是IOError
或OSError
的子OSError
(取決於您的Python版本)。 如果您查看OSError
,它會告訴您它具有一個代表基本錯誤的errno
。
那么,您獲得哪個errno
值進行超時? 我願意打賭它是EINPROGRESS
,但讓我們確定一下:
>>> urllib.urlopen('http://127.0.0.1', timeout=0)
urllib2.URLError: <urlopen error [Errno 36] Operation now in progress>
>>> errno.errorcode[36]
'EINPROGRESS'
(您可以只使用數字36,但這不能保證在所有平台上都相同; errno.EINPROGRESS
應該更便於攜帶。)
所以:
import errno
import urllib2
def retrying_urlopen(retries, *args, **kwargs):
for i in range(retries):
try:
return urllib2.urlopen(*args, **kwargs)
except URLError as e:
if e.reason.errno == errno.EINPROGRESS:
continue
raise
如果您認為這很糟糕並且應該不那么笨拙……那么,我想每個人都同意。 例外情況已經得到了兩次徹底的改進,出現了另一個大的例外,並且在此過程中進行了各種小的更改。 但是,如果堅持使用2.7,您將無法獲得這些改進的好處。
如果無法移至Python 3.4,則可能移至諸如requests
或urllib3
類的第三方模塊。 這兩個庫都有一個單獨的Timeout
異常類型,而不是讓您深入了解通用URLError
的詳細信息。
簽出requests
庫。 如果您只想等待指定的時間(而不是整個下載,僅等到從服務器收到響應),只需將timeout
參數添加到標准URL請求中,以秒為單位:
r = requests.get(url, timeout=10)
如果超過了timeout
時間,則會引發requests.exceptions.Timeout
異常,可以根據需要進行處理。 例如,您可以將請求放在try / except塊中,如果引發異常,則捕獲該異常,然后在完全失敗之前再次嘗試連接指定的次數。
您可能還需要檢出requests.adapters.HTTPAdapter
,它具有max_retries
參數。 它通常在Requests Session
,根據文檔,它通過實現Transport Adapter接口為Requests會話提供了一個通用接口來聯系HTTP和HTTPS url。
即使我是Python的新手,但我認為即使像這樣的簡單解決方案也可以解決問題,
首先將東西視為None,其中東西是page_source。 還要記住,我只考慮了URLError異常。 您可能需要根據需要添加更多內容。
import urllib2
import time
stuff=None
max_attempts=4
r=0
while stuff is None and r<max_attempts:
try:
response = urllib2.urlopen('http://www.google.com/ncr', timeout=10)
stuff = response.read()
except urllib2.URLError:
r=r+1
print "Re-trying, attempt -- ",r
time.sleep(5)
pass
print stuff
希望能有所幫助。
問候,
莫辛博士
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.