Как повторить попытку после исключения?



у меня есть цикл, начиная с for i in range(0, 100). Обычно он работает правильно, но иногда он терпит неудачу из-за сетевых условий. В настоящее время у меня он установлен так, что при сбое он будет continue в предложении except (перейдите к следующему номеру для i).



можно ли мне переназначить тот же номер на i и снова запустить неудачную итерацию цикла?

538   14  

14 ответов:

сделать while True внутри цикла for, положить try код внутри, и вырваться из этого while цикл только тогда, когда ваш код успешно.

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

Я предпочитаю ограничить количество повторных попыток, так что если есть проблема с этим конкретным элементом, вы в конечном итоге продолжите на следующий, таким образом:

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.

на повтор пакета это хороший способ повторить блок кода при сбое.

например:

@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"

вот решение, похожее на другие, но оно вызовет исключение, если оно не удастся в заданном количестве или повторных попытках.

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

более "функциональный" подход без использования этих уродливых циклов while:

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

tryAgain()

самым ясным способом было бы явно установить i. Например:

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

    except MyException:
        continue

есть что-то похожее на Python Decorator Library.

пожалуйста, имейте в виду, что он не проверяет исключения, но возвращаемое значение. Он повторяется до тех пор, пока украшенная функция не вернет True.

немного измененная версия должна сделать трюк.

С помощью рекурсии

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

общее решение с таймаутом:

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()

используя while и счетчик:

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

вы можете использовать пакет повторной попытки Python. повтор

Он написан на Python, чтобы упростить задачу добавления поведения повтора к чему угодно.

Если вы хотите решение без вложенных циклов и вызова break на успех вы могли бы разработать быстрый wrap retriable для любой итерируемый. Вот пример сетевой проблемы, с которой я сталкиваюсь, часто сохраняемая аутентификация истекает. Использование его будет выглядеть так:

client = get_client()
smart_loop = retriable(list_of_values):

for value in smart_loop:
    try:
        client.do_something_with(value)
    except ClientAuthExpired:
        client = get_client()
        smart_loop.retry()
        continue
    except NetworkTimeout:
        smart_loop.retry()
        continue

вот моя идея о том, как это исправить:

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)

увеличьте свою переменную цикла только тогда, когда предложение try успешно

Comments

    Ничего не найдено.