异常后如何重试?

问题描述 投票:210回答:17

我有一个以for i in range(0, 100)开头的循环。正常情况下,它可以正常运行,但有时由于网络条件而失败。目前,我已对其进行设置,以便在失败时将在except子句中显示为continue(继续进行i的下一个数字)。

我是否可以将相同的数字重新分配给i并再次执行循环的失败迭代?

python loops exception try-except
17个回答
325
投票

在for循环内执行while True,将您的try代码放入其中,仅在代码成功后才从该while循环中中断。

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

3
投票
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块。


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

2
投票

您可以使用Python重试包。Retrying

它是用Python编写的,以简化将重试行为添加到几乎所有内容的任务。


1
投票

如果您想要一个没有嵌套循环且成功调用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

0
投票

我在代码中使用以下代码,

   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

-1
投票

我最近与我的python合作解决了这个问题,很高兴与stackoverflow访问者分享它,如果需要的话,请提供反馈。

print("\nmonthly salary per day and year converter".title())
print('==' * 25)


def income_counter(day, salary, month):
    global result2, result, is_ready, result3
    result = salary / month
    result2 = result * day
    result3 = salary * 12
    is_ready = True
    return result, result2, result3, is_ready


i = 0
for i in range(5):
    try:
        month = int(input("\ntotal days of the current month: "))
        salary = int(input("total salary per month: "))
        day = int(input("Total Days to calculate> "))
        income_counter(day=day, salary=salary, month=month)
        if is_ready:
            print(f'Your Salary per one day is: {round(result)}')
            print(f'your income in {day} days will be: {round(result2)}')
            print(f'your total income in one year will be: {round(result3)}')
            break
        else:
            continue
    except ZeroDivisionError:
        is_ready = False
        i += 1
        print("a month does'nt have 0 days, please try again")
        print(f'total chances left: {5 - i}')
    except ValueError:
        is_ready = False
        i += 1
        print("Invalid value, please type a number")
        print(f'total chances left: {5 - i}')

-2
投票

这是我的解决方法:

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)

-9
投票

仅在try子句成功时才增加循环变量


161
投票

我更喜欢限制重试次数,这样,如果该特定项目有问题,您最终将继续进行下一个,因此:

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.

59
投票

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

17
投票

这里有一个与其他解决方案相似的解决方案,但是如果未按规定的次数或重试次数成功,它将引发异常。

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

15
投票

更“实用”的方法,而不使用那些难看的while循环:

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

tryAgain()

9
投票

最清楚的方法是显式设置i。例如:

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

    except MyException:
        continue

5
投票

使用递归

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

5
投票

具有超时的通用解决方案:

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

4
投票

Python Decorator Library中有类似内容。

请记住,它不会测试异常,而是返回值。重试,直到修饰的函数返回True。

经过稍微修改的版本应该可以解决问题。

© www.soinside.com 2019 - 2024. All rights reserved.