Jak spróbować ponownie po wyjątku?

Mam pętlę zaczynającą się od for i in range(0, 100). Zwykle działa poprawnie, ale czasami zawodzi z powodu warunków sieciowych. Obecnie mam go ustawiony tak, że po niepowodzeniu będzie continue w klauzuli except(dalej do następnego numeru dla i).

Czy jest możliwe, abym ponownie przypisał ten sam numer do i i ponownie uruchomił nieudaną iterację pętli?

Author: smci, 2010-01-18

14 answers

Wykonaj while True wewnątrz pętli for, włóż kod try do środka i przerwij tę pętlę while tylko wtedy, gdy twój Kod się powiedzie.

for i in range(0,100):
    while True:
        try:
            # do stuff
        except SomeSpecificException:
            continue
        break
 253
Author: zneak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-02 17:03:00

Wolę ograniczyć liczbę powtórzeń, tak, że jeśli pojawi się problem z danym przedmiotem, w końcu przejdziesz do następnego, a więc:

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.
 121
Author: xorsyst,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-05 15:03:37

Pakiet retrying jest dobrym sposobem na ponowne spróbowanie bloku kodu po niepowodzeniu.

Na przykład:

@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"
 46
Author: goneri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-18 12:29:43

Tutaj jest rozwiązanie podobne do innych, ale spowoduje to powstanie wyjątku, jeśli nie uda mu się wykonać określonej liczby lub powtórzeń.

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
 13
Author: TheHerk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-17 17:34:02

Bardziej "funkcjonalne" podejście bez używania brzydkich pętli while:

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

tryAgain()
 11
Author: restbeckett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-28 20:46:42

Najczystszym sposobem byłoby jawne ustawienie i. Na przykład:

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

    except MyException:
        continue
 7
Author: Tomi Kyöstilä,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-14 23:28:54

Jest coś podobnego w Python Decorator Library.

Należy pamiętać, że nie testuje wyjątków, ale zwraca wartość. Powtarza się, dopóki funkcja dekorowana nie zwróci True.

Lekko zmodyfikowana wersja powinna załatwić sprawę.

 4
Author: Michael,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-05 16:22:50

Using recursion

for i in range(100):
    def do():
        try:
            ## Network related scripts
        except SpecificException as ex:
            do()
    do() ## invoke do() whenever required inside this loop
 4
Author: Joseph Thomas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-31 12:19:14

Ogólne rozwiązanie z limitem czasu:

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)

Użycie:

for retry in onerror_retry(SomeSpecificException, do_stuff):
    retry()
 4
Author: Laurent LAPORTE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-17 12:51:31

Używanie while I licznika:

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
 2
Author: Ranju R,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-31 11:57:34

Możesz użyć Pythona retrying package. Retrying

Jest napisany w Pythonie, aby uprościć zadanie dodawania zachowania retry do niemal wszystkiego.

 1
Author: ManJan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-18 17:13:08

Jeśli chcesz mieć rozwiązanie bez zagnieżdżonych pętli i wywoływania {[1] } po sukcesie, możesz stworzyć szybkie zawijanie retriable dla każdego iterowalnego. Oto przykład problemu z siecią, na który często wpadam-zapisane uwierzytelnianie wygasa. Jego użycie brzmiałoby tak:

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
 0
Author: Mikhail,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-24 21:28:48

Oto mój pomysł jak to naprawić:

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)
 -2
Author: Amine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-09 23:47:23

Zwiększ zmienną pętli tylko wtedy, gdy klauzula try powiedzie się

 -9
Author: appusajeev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-18 09:34:27