415 Stimmen

Wie kann man es nach einer Ausnahme erneut versuchen?

Ich habe eine Schleife, die mit for i in range(0, 100) . Normalerweise läuft es korrekt, aber manchmal schlägt es aufgrund von Netzwerkbedingungen fehl. Derzeit habe ich es so eingestellt, dass es bei einem Fehler continue in der Ausnahmeklausel (weiter zur nächsten Nummer für i ).

Ist es möglich, die gleiche Nummer erneut zuzuweisen i und die fehlgeschlagene Iteration der Schleife erneut durchlaufen?

554voto

zneak Punkte 129366

Machen Sie eine while True innerhalb Ihrer for-Schleife, setzen Sie Ihre try Code im Inneren und brechen von diesem while Schleife nur, wenn Ihr Code erfolgreich ist.

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

339voto

xorsyst Punkte 6991

Ich ziehe es vor, die Anzahl der Wiederholungsversuche zu begrenzen, so dass man bei einem Problem mit einem bestimmten Element schließlich zum nächsten übergehen kann:

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.

111voto

goneri Punkte 1445

UPDATE 2021-12-01 :

Seit Juni 2016 wird das Retrying-Paket nicht mehr gepflegt. Erwägen Sie die Verwendung des aktiven Forks github.com/jd/tenacity oder alternativ github.com/litl/backoff .


En Wiederholungspaket ist eine gute Möglichkeit, einen Codeblock bei einem Fehler erneut zu versuchen.

Zum Beispiel:

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

57voto

theherk Punkte 5130

Hier ist eine Lösung, die anderen ähnelt, aber eine Ausnahme auslöst, wenn sie nicht in der vorgeschriebenen Anzahl von Wiederholungsversuchen erfolgreich ist.

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

29voto

np8 Punkte 19969

Alternativen zu retrying : tenacity y backoff (Aktualisierung 2020)

En erneuter Versuch Bibliothek war früher die beste Lösung, aber leider hat sie einige Bugs und wurde seit 2016 nicht mehr aktualisiert. Andere Alternativen scheinen zu sein Backoff y Ausdauer . Zum Zeitpunkt des Verfassens dieses Artikels hatte die Tenacity mehr GItHub-Sterne (2,3k gegenüber 1,2k) und wurde vor kurzem aktualisiert, daher habe ich mich für sie entschieden. Hier ist ein Beispiel:

from functools import partial
import random # producing random errors for this example

from tenacity import retry, stop_after_delay, wait_fixed, retry_if_exception_type

# Custom error type for this example
class CommunicationError(Exception):
    pass

# Define shorthand decorator for the used settings.
retry_on_communication_error = partial(
    retry,
    stop=stop_after_delay(10),  # max. 10 seconds wait.
    wait=wait_fixed(0.4),  # wait 400ms 
    retry=retry_if_exception_type(CommunicationError),
)()

@retry_on_communication_error
def do_something_unreliable(i):
    if random.randint(1, 5) == 3:
        print('Run#', i, 'Error occured. Retrying.')
        raise CommunicationError()

for i in range(100):
    do_something_unreliable(i)

Der obige Code gibt etwa Folgendes aus:

Run# 3 Error occured. Retrying.
Run# 5 Error occured. Retrying.
Run# 6 Error occured. Retrying.
Run# 6 Error occured. Retrying.
Run# 10 Error occured. Retrying.
.
.
.

Weitere Einstellungen für das tenacity.retry sind auf der Website tenacity GitHub-Seite .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X