2016-07-15 63 views
1

我有以下的裝飾應處理「無網絡」例外:這個python裝飾器有什麼問題?

class NetworkError(RuntimeError): 
    pass 

def reTryer(max_retries=5, timeout=5): 
    def wraper(func): 
     request_exceptions = (
      requests.exceptions.Timeout, 
      requests.exceptions.ConnectionError, 
      requests.exceptions.HTTPError 
     ) 
     def inner(*args, **kwargs): 
      for i in range(max_retries): 
       try: 
        result = func(*args, **kwargs) 
       except request_exceptions: 
        time.sleep(timeout) 
        print("Bad or broken connection, trying again...") 
        continue 
       else: 
        return result 
      else: 
       raise NetworkError 
     return inner 
    return wraper 

不過,這並不在所有的工作,甚至有沒有「不良或斷開連接,重新嘗試......」輸出時我的LAN適配器處於斷開狀態,它什麼也沒有顯示。這是func的定義和調用:

@reTryer(5,5) 
def func(arg): 
    #some code 

func(arg) 

我是否錯過了什麼?

+0

你嘗試在'inner'功能來定義的元組'request_exceptions'? – Frodon

+0

@Frodon會發生什麼變化? – glglgl

+0

@Frodon無關緊要,內部函數可以訪問外部函數範圍內的任何變量。 –

回答

2

要回答你的問題:

作爲實施似乎是正確的,我可以想像,有些事情可能是問題的原因。

主要是我考慮裝飾函數永遠不會返回,拋出一個不同於你聚焦的異常,甚至返回正常。

您可以用

@reTryer(2, 1.0) 
def always_ok(): 
    print "ok" 

@reTryer(2, 1.0) 
def always_good_error(): 
    print "good error" 
    raise requests.exceptions.Timeout 

@reTryer(2, 1.0) 
def always_bad_error(): 
    print "bad error" 
    raise RuntimeError 

測試這個我得到

>>> always_ok() 
ok 
>>> import time 
>>> always_good_error() 
good error 
Bad or broken connection, trying again... 
good error 
Bad or broken connection, trying again... 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 17, in inner 
__main__.NetworkError 
>>> always_bad_error() 
bad error 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "<stdin>", line 9, in inner 
    File "<stdin>", line 4, in always_bad_error 
RuntimeError 
>>> 
+0

確切地說,很確定它只是'返回'沒有引發異常。 –

+0

謝謝你的回答。根據你的建議,我會進一步調查這個問題。 –