11 Stimmen

Wiederholung von Python-Funktionsaufrufen bei Ausnahmen?

Hallo zusammen, ich arbeite an einem Daten-Scraping-Projekt und ich bin auf der Suche nach einer sauberen Möglichkeit, einen Funktionsaufruf zu wiederholen, wenn eine Ausnahme ausgelöst wird.

Pseudocode:

try:
    myfunc(x)
except myError:
    ###try to call myfunc(x) again Y number of times, 
        until success(no exceptions raised) otherwise raise myError2

Mir ist klar, dass dies nicht die beste Vorgehensweise ist, aber ich arbeite mich durch eine Reihe von verschiedenen Code-/Netzwerkschichten, die nicht zuverlässig sind, und ich kann sie realistischerweise nicht debuggen.

Im Moment erreiche ich dies mit einer großen Anzahl von Versuchen \except Blöcke, und mir bluten die Augen.

Elegante Ideen gefällig?

13voto

user470379 Punkte 4809

Um genau das zu erreichen, was Sie wollen, könnten Sie etwa wie folgt vorgehen:

import functools
def try_x_times(x, exceptions_to_catch, exception_to_raise, fn):
    @functools.wraps(fn) #keeps name and docstring of old function
    def new_fn(*args, **kwargs):
        for i in xrange(x):
            try:
                return fn(*args, **kwargs)
            except exceptions_to_catch:
                 pass
        raise exception_to_raise
    return new_fn

Dann verpacken Sie einfach die alte Funktion in diese neue Funktion:

#instead of
#risky_method(1,2,'x')
not_so_risky_method = try_x_times(3, (MyError,), myError2, risky_method)
not_so_risky_method(1,2,'x')

#or just
try_x_times(3, (MyError,), myError2, risky_method)(1,2,'x')

8voto

Ming-Tang Punkte 16979

Eine Schleife verwenden

i = 0
while True:
  try: myfunc(x); break;
  except myError:
    i = i + 1;
    # print "Trying again"
    if i > 5: raise myError2;

4voto

primroot Punkte 1656
for x in xrange(num_retries):
    try:
        myFunc()
    except MyError, err:
        continue
        #time.sleep(1)
    err = None
    break
if err:
    raise MyError2
#else:
#    print "Success!"

4voto

binithb Punkte 1751

Ausnahme wie üblich nach n Wiederholungsversuchen auslösen

from functools import wraps

def retry(times):
    """
    Decorator to retry any functions 'times' times.
    """
    def retry_decorator(func):
        @wraps(func)
        def retried_function(*args, **kwargs):
            for i in range(times - 1):
                try:
                    func(*args, **kwargs)
                    return
                except Exception:  
                    pass
            func(*args, **kwargs)

        return retried_function

    return retry_decorator

# test

attempts = 3

@retry(4)
def function_that_raises_error():
    global attempts
    if 0 < attempts:
        print("fail")
        attempts -= 1
        raise Exception

    print("pass")

function_that_raises_error()

1voto

Jochen Ritzel Punkte 99416

Ich mag es, diese Probleme mit Rekursion zu lösen:

def tryfor(times, on_failure, excepts, func, *args, **kwargs):
    if times < 1:
        raise on_failure()
    try:
        return func(*args, **kwargs)
    except excepts:
        return tryfor(times-1, on_failure, excepts, func, *args, **kwargs)

tryfor(3, PermanentException, (SomeError,), dostuff,1,2)

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