Question

J'ai une boucle commençant par for i in range(0, 100). Normalement, il fonctionne correctement, mais parfois il échoue en raison des conditions du réseau. À l'heure actuelle, je l'ai réglé de telle sorte que en cas d'échec, il continue à l'exception de l'alinéa (continuer sur le numéro suivant pour i).

moi Est-il possible de réaffecter le même numéro à i et courir à travers l'itération de la boucle a échoué à nouveau?

Était-ce utile?

La solution

Faites un while True dans votre boucle, mettez votre code try à l'intérieur, et de briser cette boucle de while que lorsque votre code réussit.

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

Autres conseils

Je préfère limiter le nombre de réitérations, de sorte que s'il y a un problème avec ce point précis, vous finirez par continuer sur la suivante, ainsi:

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.

Le package est réessayant une belle façon de réessayer un bloc de code en cas d'échec.

Par exemple:

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

Voici une solution similaire à d'autres, mais il soulèvera l'exception si elle ne réussit pas dans le nombre prescrit ou relances.

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

L'approche plus « fonctionnelle » sans utiliser les laids while:

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

tryAgain()

La façon la plus claire serait de définir explicitement i. Par exemple:

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

    except MyException:
        continue

Utilisation récursivité

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

Une solution générique avec un délai d'attente:

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)

Utilisation:

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

Il y a quelque chose de similaire dans le Python décorateur Bibliothèque .

S'il vous plaît garder à l'esprit qu'il ne teste pas des exceptions, mais la valeur de retour. Il réessaie jusqu'à ce que la fonction décorée retourne True.

Une version légèrement modifiée devrait faire l'affaire.

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

Ma version est similaire à plusieurs de ce qui précède, mais ne pas utiliser une boucle de while séparée et re-raise la dernière exception si toutes les tentatives échouent. Pourrait définir explicitement err = None en haut, mais pas strictement nécessaire car il ne doit exécuter le bloc de else finale s'il y avait une erreur et donc err est réglé.

Utilisation de temps et un compteur:

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

Vous pouvez utiliser package Python réessayant. Retrying

Il est écrit en Python pour simplifier la tâche d'ajouter une nouvelle tentative comportement à peu près tout.

Si vous voulez une solution sans boucles imbriquées et l'invocation break sur le succès que vous pourriez développeur un retriable wrap rapide pour tout itérable. Voici un exemple d'un problème de mise en réseau que je rencontre souvent - sauvé l'authentification expire. L'utilisation de ce lirait comme ceci:

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'utilise suivre dans mes codes,

   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
i récemment travaillé

avec mon python sur une solution à ce problème et je suis heureux de partager avec les visiteurs stackoverflow s'il vous plaît donner des commentaires si elle est nécessaire.

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

Voici mon idée sur la façon de résoudre ce problème:

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)

incrémenter la variable de boucle uniquement lorsque la clause try réussit

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top