2010-01-18 31 views
125

我有一個從for i in range(0, 100)開始的循環。通常它運行正常,但有時由於網絡條件而失敗。目前,我已經設置了它,以便在失敗時,它將在除外條款中爲continue(繼續到i的下一個數字)。如何在python中異常後重試?

我可以重新分配相同的數字到i並再次運行循環的失敗迭代嗎?

+0

您可以使用不帶第一個參數的'range(100)'。如果你使用Python 2.x,你甚至可以使用'xrange(100)',這會生成一個迭代器並使用更少的內存。 (並不是說只有100個對象很重要。) – 2010-01-18 06:50:54

+1

可能的重複[是否有pythonic的方式來嘗試一些最多次?](http://stackoverflow.com/questions/567622/is-there- pythonic-way-to-try-something-up-to-a-maximum-number-times-times) – 2014-05-12 07:23:30

+3

這個問題可能會有幫助:[是否有pythonic方法來嘗試最多次數? ](http://stackoverflow.com/questions/567622/is-there-a-pythonic-way-to-try-something-up-to-a-maximum-number-of-times) – 2010-08-18 19:58:59

回答

213

在您的for循環中執行while True,將您的try代碼放在裏面,並且只有在代碼成功時才從while循環中斷開。

for i in range(0,100): 
    while True: 
     try: 
      # do stuff 
     except SomeSpecificException: 
      continue 
     break 
+31

除了使用'SomeSpecificError:'而不是捕獲所有異常。 – 2010-01-18 05:21:55

+0

'continue'不使用可迭代的元素;而是繼續下一個。 – 2010-01-18 05:22:31

+0

@Ignacio:是的;問題在哪裏? – zneak 2010-01-18 05:27:37

6

最明確的方法是明確設置i。例如:

i = 0 
while i < 100: 
    i += 1 
    try: 
     # do stuff 

    except MyException: 
     continue 
+31

那是C還是C++?我不知道。 – 2010-01-18 06:52:24

+2

@Georg正如問題中所述,這就是Python。或者出於某種原因你在諷刺嗎? – 2010-01-18 15:29:04

+1

這不會做OP所要求的。如果你在'#do stuff'之後加上'i + = 1',它可能會出現。 – 2013-10-20 19:20:08

-9

增量只有當try子句成功

+8

-1,細化和語法和標點符號一樣好。 – 2013-08-29 00:52:58

9

更「實用」法不使用那些醜陋的循環變量,同時循環:

def tryAgain(retries=0): 
    if retries > 10: return 
    try: 
     # Do stuff 
    except: 
     retries+=1 
     tryAgain(retries) 

tryAgain() 
+10

我很抱歉,但它看起來比「醜陋的while循環」變體更醜陋;並且我喜歡函數式編程... – lvella 2011-09-09 17:39:52

+6

但是,您需要確保您不會深入考慮 - Python中的默認堆棧大小爲1000 – 2014-08-21 10:40:26

+2

如果這將是「功能性」,則遞歸應爲:「除:tryAgain(retries + 1)' – quamrana 2017-08-01 13:18:22

3

有一個在類似的東西Python Decorator Library

請注意,它不會測試例外情況,而是測試返回值。它重試,直到裝飾函數返回True。

稍作修改後的版本應該可以做到。

+0

以下是修改例外情況的方法http://www.saltycrane.com/blog/2009/11/trying-out-retry-decorator-python/ – 2015-06-25 08:50:04

107

我傾向於限制重試次數,所以,如果有與特定項目的問題,你最終會繼續到下一個,即:

for i in range(100): 
    for attempt in range(10): 
    try: 
     # do thing 
    except: 
     # perhaps reconnect, etc. 
    else: 
     break 
    else: 
    # we failed all the attempts - deal with the consequences. 
+0

第二種方法的後果是什麼與流量控制有關的「else」?在哪些情況下執行代碼的「我們失敗...」部分? – g33kz0r 2015-01-28 05:30:36

+0

@ g33kz0r Python中的for-else構造在for循環沒有中斷時執行else子句。因此,在這種情況下,如果我們嘗試全部10次嘗試並且總是得到異常,那麼該節將執行。 – xorsyst 2015-01-28 11:25:01

+2

這是一個很好的答案!真的值得更多upvotes。它完美地使用了Python中的所有工具,特別是''for'中鮮爲人知的'else:'子句。 – pepoluan 2015-04-21 07:18:30

38

retrying package是重試的好方法代碼塊失敗。

例如:

@retry(wait_random_min=1000, wait_random_max=2000) 
def wait_random_1_to_2_s(): 
    print "Randomly wait 1 to 2 seconds between retries" 
+1

更一般地說,pypi具有多個重試修飾器包: https://pypi.python.org/pypi?%3Aaction=search&term=retry+decorator&submit=search – kert 2016-04-16 21:14:02

4

一個超時的通用解決方案:

import time 

def onerror_retry(exception, callback, timeout=2, timedelta=.1): 
    end_time = time.time() + timeout 
    while True: 
     try: 
      yield callback 
      break 
     except exception: 
      if time.time() > end_time: 
       raise 
      elif timedelta > 0: 
       time.sleep(timedelta) 

用法:

for retry in onerror_retry(SomeSpecificException, do_stuff): 
    retry() 
+0

是否可以指定單獨的函數進行錯誤檢查?它會將回調和傳遞的輸出傳遞給錯誤檢查函數,以決定它是失敗還是成功,而不是使用簡單的'except exception:' – 2017-10-10 21:04:16

+0

而不是'try ... except',您可以使用'if'聲明。但它不太pythonic。 – 2017-10-10 21:07:49

-3

下面是我對如何解決這一問題的想法:

j = 19 
def calc(y): 
    global j 
    try: 
     j = j + 8 - y 
     x = int(y/j) # this will eventually raise DIV/0 when j=0 
     print("i = ", str(y), " j = ", str(j), " x = ", str(x)) 
    except: 
     j = j + 1 # when the exception happens, increment "j" and retry 
     calc(y) 
for i in range(50): 
    calc(i) 
+6

這是離開基地。 – 2016-08-06 22:01:06

8

這是一個類似於其他的解決方案,但是如果它在規定的編號或重試中沒有成功,它將引發異常。

tries = 3 
for i in range(tries): 
    try: 
     do_the_thing() 
    except KeyError as e: 
     if i < tries - 1: # i is zero indexed 
      continue 
     else: 
      raise 
    break 
+0

大抓住@notpeter。固定。 – TheHerk 2016-05-26 18:35:33

+0

很好的答案,但變量名'retries'具有誤導性。它應該是「嘗試」。 – Lukas 2016-08-17 16:48:31

+0

真@Lukas。固定。 – TheHerk 2016-08-17 17:33:33

2

使用一段時間,計數器:

count = 1 
while count <= 3: # try 3 times 
    try: 
     # do_the_logic() 
     break 
    except SomeSpecificException as e: 
     # If trying 3rd time and still error?? 
     # Just throw the error- we don't have anything to hide :) 
     if count == 3: 
      raise 
     count += 1 
3

使用遞歸

for i in range(100): 
    def do(): 
     try: 
      ## Network related scripts 
     except SpecificException as ex: 
      do() 
    do() ## invoke do() whenever required inside this loop 
0

您可以使用Python重試包。 Retrying

它是用Python編寫的,以簡化向任何事物添加重試行爲的任務。