Как повторить попытку после исключения?
у меня есть цикл, начиная с for i in range(0, 100). Обычно он работает правильно, но иногда он терпит неудачу из-за сетевых условий. В настоящее время у меня он установлен так, что при сбое он будет continue в предложении except (перейдите к следующему номеру для i).
можно ли мне переназначить тот же номер на i и снова запустить неудачную итерацию цикла?
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на успех вы могли бы разработать быстрый wrapretriableдля любой итерируемый. Вот пример сетевой проблемы, с которой я сталкиваюсь, часто сохраняемая аутентификация истекает. Использование его будет выглядеть так: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)
Comments