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

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

Возможно ли, чтобы я переназначил тот же номер до i и снова пропустил неудачную итерацию цикла?

Ответ 1

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

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

Ответ 2

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

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.

Ответ 3

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

Например:

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

Ответ 4

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

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

Ответ 5

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

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

tryAgain()

Ответ 6

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

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

    except MyException:
        continue

Ответ 7

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

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

Ответ 8

В библиотеке Python Decorator есть нечто похожее.

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

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

Ответ 9

Использование рекурсии

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

Ответ 10

Использование 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

Ответ 11

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

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

Ответ 12

Если вы хотите найти решение без вложенных циклов и использования break при успехе, вы можете разработать быструю 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

Ответ 13

Я использую следующие в моих кодах,

   for i in range(0, 10):
    try:
        #things I need to do
    except ValueError:
        print("Try #{} failed with ValueError: Sleeping for 2 secs before next try:".format(i))
        time.sleep(2)
        continue
    break

Ответ 14

for _ in range(5):
    try:
        # replace this with something that may fail
        raise ValueError("foo")

    # replace Exception with a more specific exception
    except Exception as e:
        err = e
        continue

    # no exception, continue remainder of code
    else:
        break

# did not break the for loop, therefore all attempts
# raised an exception
else:
    raise err

Моя версия похожа на несколько выше, но не использует отдельный во while цикла, и вновь поднимает последнее исключение, если все повторные попытки терпят неудачу. Можно явно установить err = None наверху, но это не является строго необходимым, поскольку он должен выполнять только последний блок else если произошла ошибка и, следовательно, установлен err.

Ответ 15

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

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)

Ответ 16

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