Pregunta

Tengo un bucle a partir de for i in range(0, 100). Normalmente se ejecuta correctamente, pero a veces falla debido a condiciones de la red. Actualmente lo tengo configurado de manera que en caso de fallo, se continue en la cláusula de excepción (continuar con el siguiente número de i).

¿Es posible que yo pueda reasignar el mismo número a i y ejecutar a través de la iteración del bucle fallado otra vez?

¿Fue útil?

Solución

Hacer una while True dentro de su bucle, ponga su código try dentro, y romper de ese bucle while sólo cuando su código tiene éxito.

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

Otros consejos

Yo prefiero limitar el número de intentos, por lo que si hay un problema con ese elemento específico es muy probable que continúe a la siguiente, así:

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.

El paquete de volver a intentar es una buena manera de volver a intentar un bloque de código en caso de fallo.

Por ejemplo:

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

Aquí es una solución similar a otros, sino que aumentará la excepción si no tiene éxito en el número de reintentos o prescrito.

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

El enfoque más "funcional" sin necesidad de utilizar esos feos mientras bucles:

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

tryAgain()

La forma más clara sería la de establecer explícitamente i. Por ejemplo:

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

    except MyException:
        continue

Uso de recursión

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

una solución genérica con un tiempo de espera:

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)

Uso:

for retry in onerror_retry(SomeSpecificException, do_stuff):
    retry()

No es algo similar en el Python decorador Biblioteca .

Por favor, tenga en cuenta que no prueba para las excepciones, pero el valor de retorno. Se vuelve a intentar hasta que la función devuelve True decorada.

Una versión ligeramente modificada debe hacer el truco.

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

Mi versión es similar a varias de las anteriores, pero no utiliza un bucle while separada, y re-plantea la última excepción si todos los reintentos fallan. Podría establecer explícitamente err = None en la parte superior, pero no es estrictamente necesario, ya que sólo debe ejecutar el bloque else final si hubo un error y por lo tanto se establece err.

Uso de tiempo y un contador de:

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

Puede utilizar el paquete de volver a intentar Python. Reintentando

Está escrito en Python para simplificar la tarea de añadir reintentar el comportamiento de casi cualquier cosa.

Si desea una solución sin bucles anidados y break invocando el éxito que podía desarrollador retriable una envoltura rápida para cualquier iterable. He aquí un ejemplo de un problema de red que me encuentro con frecuencia - salvaron la autenticación caduca. El uso de ella leería así:

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

Yo uso siguiente en mis códigos,

   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

Hace poco trabajé con mi pitón en una solución a este problema y estoy feliz de compartir con los visitantes stackoverflow favor dar información si es necesario.

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}')

Esta es mi idea sobre cómo solucionar este problema:

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)

incrementar la variable de bucle sólo cuando la cláusula try tiene éxito

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top