我有一个循环,开头为for I,范围为(0,100)。正常情况下,它可以正常运行,但有时由于网络条件而出现故障。目前,我已经设置它,以便在失败时,它将继续在except子句中(继续到I的下一个数字)。

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


当前回答

如果您正在寻找的是重新尝试x次失败的尝试,那么单个for else循环可能就是您想要的。考虑这个例子,尝试了3次:

attempts = 3

for attempt in range(1, attempts+1):
    try:
        if attempt < 4:
            raise TypeError(f"Error raised on attempt: {attempt}")
        else:
            print(f'Attempt {attempt} finally worked.')
    except (TypeError) as error:
        print(f'Attempt {attempt} hit the exception.')
        continue
    else:
        break
else:
    print(f'Exit after final attempt: {attempt}')

print(f'\nGo on to execute other code ...')

给出输出:

Attempt 1 hit the exception.
Attempt 2 hit the exception.
Attempt 3 hit the exception.
Exit after final attempt: 3

Go on to execute other code ...

再试一次它就成功了

attempts = 4

给出输出:

Attempt 1 hit the exception.
Attempt 2 hit the exception.
Attempt 3 hit the exception.
Attempt 4 finally worked.

Go on to execute other code ...

其他回答

以下是我关于如何解决这个问题的想法:

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)

以下是我对这个问题的看法。下面的重试功能支持以下特性:

当调用成功时返回被调用函数的值 如果尝试失败,则引发被调用函数的异常 尝试次数限制(0表示无限) 在尝试之间等待(线性或指数) 仅当异常是特定异常类型的实例时重试。 可选的尝试记录

import time

def retry(func, ex_type=Exception, limit=0, wait_ms=100, wait_increase_ratio=2, logger=None):
    attempt = 1
    while True:
        try:
            return func()
        except Exception as ex:
            if not isinstance(ex, ex_type):
                raise ex
            if 0 < limit <= attempt:
                if logger:
                    logger.warning("no more attempts")
                raise ex

            if logger:
                logger.error("failed execution attempt #%d", attempt, exc_info=ex)

            attempt += 1
            if logger:
                logger.info("waiting %d ms before attempt #%d", wait_ms, attempt)
            time.sleep(wait_ms / 1000)
            wait_ms *= wait_increase_ratio

用法:

def fail_randomly():
    y = random.randint(0, 10)
    if y < 10:
        y = 0
    return x / y


logger = logging.getLogger()
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler(stream=sys.stdout))

logger.info("starting")
result = retry.retry(fail_randomly, ex_type=ZeroDivisionError, limit=20, logger=logger)
logger.info("result is: %s", result)

更多信息请看我的帖子。

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。

使用这个装饰器,您可以轻松地控制错误

class catch:
    def __init__(self, max=1, callback=None):
        self.max = max 
        self.callback = callback 
    
    def set_max(self, max):
        self.max = max
    
    def handler(self, *args, **kwargs):
        self.index = 0
        while self.index < self.max: 
            self.index += 1
            try:
                self.func(self, *args, **kwargs)
        
            except Exception as error:
                if callable(self.callback):
                    self.callback(self, error, args, kwargs)
                
    def __call__(self, func):
        self.func = func
        return self.handler

import time
def callback(cls, error, args, kwargs):
    print('func args', args, 'func kwargs', kwargs)
    print('error', repr(error), 'trying', cls.index)
    if cls.index == 2:
        cls.set_max(4)
    
    else:
        time.sleep(1)
    
    
@catch(max=2, callback=callback)  
def test(cls, ok, **kwargs):
    raise ValueError('ok')

test(1, message='hello')

尝试次数= 3 而尝试: 试一试: ... ... <状态好了> 打破 除了: 尝试- = 1 Else: #已执行的唯一break未被引发 < >失败状态