Python try-else

Jakie jest zamierzone wykorzystanie opcjonalnej klauzuli else deklaracji try?

Author: Honest Abe, 2009-05-13

20 answers

Polecenia w bloku else są wykonywane, jeśli wykonanie spadnie z dołu try - jeśli nie było wyjątku. Szczerze, nigdy nie znalazłem potrzeby.

Jednakże Obsługa wyjątków uwagi:

Użycie klauzuli else jest lepsze niż dodanie dodatkowego kodu do próby klauzula, ponieważ pozwala uniknąć przypadkowego łapanie wyjątku, który nie był / align = "left" / próba ... poza oświadczeniem.

Więc, jeśli masz metodę, która może na przykład rzucić IOError, i chcesz wyłapać wyjątki, które wywołują, ale jest coś innego, co chcesz zrobić, jeśli pierwsza operacja się powiedzie, a nie chcesz wyłapać IOError z tej operacji, możesz napisać coś takiego: {[13]]}

    try:
        operation_that_can_throw_ioerror()
    except IOError:
        handle_the_exception_somehow()
    else:
         # we don't want to catch the IOError if it's raised
        another_operation_that_can_throw_ioerror()
    finally:
        something_we_always_need_to_do()

Jeśli umieścisz another_operation_that_can_throw_ioerror() Po operation_that_can_throw_ioerror, except wychwyci błędy drugiego wywołania. I jeśli umieścisz go po całym try bloku, zawsze będzie uruchamiany, i dopiero po finally. Na else pozwala upewnić się

  1. druga operacja jest uruchamiana tylko wtedy, gdy nie ma wyjątku,
  2. jest uruchamiany przed finally blokiem i
  3. any IOErrors it raises are ' t caught here

 704
Author: Blair Conrad,
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
2009-05-13 10:40:04

Jest jeden duży powód do używania else - styl i czytelność. Ogólnie dobrym pomysłem jest trzymanie kodu, który może powodować wyjątki w pobliżu kodu, który się nimi zajmuje. Na przykład, porównaj te:

try:
    from EasyDialogs import AskPassword
    # 20 other lines
    getpass = AskPassword
except ImportError:
    getpass = default_getpass

I

try:
    from EasyDialogs import AskPassword
except ImportError:
    getpass = default_getpass
else:
    # 20 other lines
    getpass = AskPassword

Drugi jest dobry, gdy except nie może wrócić wcześniej, lub ponownie wyrzucić wyjątek. Jeśli to możliwe, napisałbym:

try:
    from EasyDialogs import AskPassword
except ImportError:
    getpass = default_getpass
    return False  # or throw Exception('something more descriptive')

# 20 other lines
getpass = AskPassword

Uwaga: odpowiedź skopiowana z ostatnio zamieszczonego duplikatu tutaj , stąd całe to " AskPassword" rzeczy.

 81
Author: Izkata,
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-01-17 11:59:25

Jedno użycie: przetestuj kod, który powinien wywołać wyjątek.

try:
    this_should_raise_TypeError()
except TypeError:
    pass
except:
    assert False, "Raised the wrong exception type"
else:
    assert False, "Didn't raise any exception"

(Ten kod powinien zostać skrócony do bardziej ogólnego testu w praktyce.)

 42
Author: Darius Bacon,
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
2009-05-13 02:36:39

Python try-else

Jakie jest przeznaczenie opcjonalnej klauzuli else Instrukcji TRY?

Podsumowanie

Instrukcja else działa, jeśli nie ma wyjątków i jeśli nie jest przerwana przez return, continue, lub break oświadczenie.

W pozostałych odpowiedziach brakuje tej ostatniej części.

Z dokumentów:

Opcjonalna klauzula else jest wykonywana, gdy i kiedy kontrolka wypływa z end klauzuli try.*

(Dodano pogrubienie.), A przypis brzmi:

*obecnie Kontrola "wypływa z końca", z wyjątkiem przypadku wyjątek lub wykonanie return, continue, lub break oświadczenie.

Wymaga co najmniej jednej klauzuli poprzedzającej except (patrz gramatyka ). Tak naprawdę nie jest to "try-else", tylko " try-except-else (- finally)", przy czym else (i finally) są opcjonalne.

The Python Tutorial opracowano na podstawie materiału źródłowego.]}

Próba ... except statement posiada opcjonalną klauzulę else, która, gdy obecny, musi spełniać wszystkie z wyjątkiem klauzul. Jest to przydatne dla kodu, który musi zostać wykonane, jeśli klauzula try nie wywołuje wyjątku. Na przykład:
for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except IOError:
        print 'cannot open', arg
    else:
        print arg, 'has', len(f.readlines()), 'lines'
        f.close()

Użycie klauzuli else jest lepsze niż dodawanie dodatkowego kodu do klauzula try, ponieważ pozwala uniknąć przypadkowego przechwycenia wyjątku to nie zostało podniesione przez kod chroniony przez próbę ... z wyjątkiem oświadczenie.

Przykład różnicowania else w stosunku do kodu po try bloku

Jeśli obsłużysz błąd, blok else nie uruchomi się. Na przykład:

def handle_error():
    try:
        raise RuntimeError('oops!')
    except RuntimeError as error:
        print('handled a RuntimeError, no big deal.')
    else:
        print('if this prints, we had no error!') # won't print!
    print('And now we have left the try block!')  # will print!

A teraz

>>> handle_error()
handled a RuntimeError, no big deal.
And now we have left the try block!
 29
Author: Aaron Hall,
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-06-07 22:14:34

Uważam, że jest to naprawdę przydatne, gdy masz do zrobienia sprzątanie, które musi być zrobione, nawet jeśli jest wyjątek:

try:
    data = something_that_can_go_wrong()
except Exception as e: # yes, I know that's a bad way to do it...
    handle_exception(e)
else:
    do_stuff(data)
finally:
    clean_up()
 13
Author: RoadieRich,
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
2015-03-04 00:22:39

Nawet jeśli nie możesz myśleć o użyciu go teraz, Można założyć, że nie musi być zastosowanie do niego. Oto niewyobrażalna próbka:

Z else:

a = [1,2,3]
try:
    something = a[2]
except:
    print "out of bounds"
else:
    print something

Bez else:

try:
    something = a[2]
except:
    print "out of bounds"

if "something" in locals():
    print something

Tutaj masz zmienną something zdefiniowaną, jeśli nie zostanie wyrzucony błąd. Można to usunąć poza blokiem try, ale wtedy wymaga to pewnego brudnego wykrywania, jeśli zmienna jest zdefiniowana.

 12
Author: Unknown,
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
2015-03-04 00:27:03

Try-except-else świetnie nadaje się do łączenia wzoru EAFP z kaczka-typowanie :

try:
  cs = x.cleanupSet
except AttributeError:
  pass
else:
  for v in cs:
    v.cleanup()

Możesz pomyśleć, że ten naiwny kod jest w porządku:

try:
  for v in x.cleanupSet:
    v.clenaup()
except AttributeError:
  pass

Jest to świetny sposób na przypadkowe ukrywanie poważnych błędów w kodzie. Wpisałem tam czyszczenie, ale błąd atrybutu, który dałby mi znać, został połknięty. Co gorsza, co jeśli napisałem to poprawnie, ale metoda czyszczenia była czasami przekazywana typ użytkownika, który miał błędnie nazwany atrybut, powodując, że cicho nie udało się w połowie i nie Zamknięto pliku? Powodzenia w debugowaniu tego.

 11
Author: Alice Purcell,
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
2015-04-17 22:11:22

From błędy i wyjątki # Obsługa wyjątków - docs.python.org

Twierdzenie try ... except ma klauzulę opcjonalną else, która, gdy są obecne, muszą przestrzegać wszystkich z wyjątkiem klauzul. Jest to przydatne dla kodu to musi zostać wykonane, jeśli klauzula try nie wywołuje wyjątku. Na przykład:

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except IOError:
        print 'cannot open', arg
    else:
        print arg, 'has', len(f.readlines()), 'lines'
        f.close()

Użycie klauzuli else jest lepsze niż dodawanie dodatkowego kodu do klauzula try, ponieważ pozwala uniknąć przypadkowego przechwycenia wyjątku to nie było wychowane kod jest chroniony przez próbę ... z wyjątkiem oświadczenie.

 8
Author: fedorqui,
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-08-21 12:29:59

Jest ładny przykład try-else W PEP 380 . Zasadniczo sprowadza się to do wykonywania różnych WYJĄTKÓW w różnych częściach algorytmu.

To jest coś takiego:

try:
    do_init_stuff()
except:
    handle_init_suff_execption()
else:
    try:
        do_middle_stuff()
    except:
        handle_middle_stuff_exception()

Pozwala to na pisanie kodu obsługi wyjątków bliżej miejsca, w którym występuje wyjątek.

 6
Author: itsadok,
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
2009-05-27 11:39:02

Patrząc na odniesienie do Pythona wydaje się, że else jest wykonywane po try, gdy nie ma wyjątku. Opcjonalna klauzula else jest wykonywana, gdy kontrolka wypływa z końca klauzuli try. 2 wyjątki w klauzuli else nie są obsługiwane przez poprzednie klauzule except.

Dive into python mA przykład, gdzie, jeśli dobrze rozumiem, w try bloku próbują zaimportować moduł, gdy to się nie powiedzie, dostajesz wyjątek i bind domyślny, ale gdy to dziaĹ 'ania masz moĹźliwoĹ" Ä ‡ wejĹ "cia w else block i zwiÄ ... zania co jest wymagane (patrz link do przykĹ 'adu i wyjaĹ" nienia).

Jeśli próbowałeś pracować w bloku catch, może to spowodować kolejny wyjątek - chyba właśnie tam przydaje się Blok else.

 4
Author: stefanB,
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
2015-03-04 00:33:06

To wszystko. Blok "else" klauzuli try-except istnieje dla kodu, który uruchamia się, gdy (i tylko wtedy, gdy) próbowana operacja powiedzie się. Może być używany i może być nadużywany.

try:
    fp= open("configuration_file", "rb")
except EnvironmentError:
    confdata= '' # it's ok if the file can't be opened
else:
    confdata= fp.read()
    fp.close()

# your code continues here
# working with (possibly empty) confdata
Osobiście podoba mi się i używam go, gdy jest to właściwe. Semantycznie grupuje wypowiedzi.
 3
Author: tzot,
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
2009-05-14 20:43:20

Większość odpowiedzi wydaje się skupiać na tym, dlaczego nie możemy po prostu umieścić materiału w klauzuli else w samej klauzuli try. Klauzula question else w instrukcji try... do czego służy konkretnie pyta, dlaczego kod klauzuli else nie może przejść Po samego bloku try I to pytanie jest przypisane do tego, ale nie widzę tu jednoznacznej odpowiedzi na to pytanie. I feel https://stackoverflow.com/a/3996378/1503120 doskonale odpowiada na to pytanie. Próbowałem też aby wyjaśnić różne znaczenie różnych klauzul w https://stackoverflow.com/a/22579805/1503120 .

 3
Author: jamadagni,
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-05-23 12:03:08

Być może przydałoby się:

#debug = []

def debuglog(text, obj=None):
    " Simple little logger. "
    try:
        debug   # does global exist?
    except NameError:
        pass    # if not, don't even bother displaying
    except:
        print('Unknown cause. Debug debuglog().')
    else:
        # debug does exist.
        # Now test if you want to log this debug message
        # from caller "obj"
        try:
            if obj in debug:
                print(text)     # stdout
        except TypeError:
            print('The global "debug" flag should be an iterable.')
        except:
            print('Unknown cause. Debug debuglog().')

def myfunc():
    debuglog('Made it to myfunc()', myfunc)

debug = [myfunc,]
myfunc()

Może to również doprowadzi Cię do użycia.

 2
Author: DevPlayer,
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-05-20 22:12:04

Blok else często może istnieć w celu uzupełnienia funkcjonalności, która występuje w każdym bloku except.

try:
    test_consistency(valuable_data)
except Except1:
    inconsistency_type = 1
except Except2:
    inconsistency_type = 2
except:
    # Something else is wrong
    raise
else:
    inconsistency_type = 0

"""
Process each individual inconsistency down here instead of
inside the except blocks. Use 0 to mean no inconsistency.
"""

W tym przypadku {[3] } jest ustawione w każdym bloku z wyjątkiem, tak że zachowanie jest uzupełniane w przypadku braku błędu w else.

Oczywiście, opisuję to jako wzór, który może kiedyś pojawić się w Twoim kodzie. W tym konkretnym przypadku przed blokiem try ustawiasz inconsistency_type na 0.

 1
Author: Wesley,
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
2009-05-14 21:07:30

Znalazłem try: ... else: Konstruktor przydatny w sytuacji, gdy uruchamiasz zapytania do bazy danych i rejestrujesz wyniki tych zapytań do oddzielnej bazy danych o tym samym smaku/typie. Załóżmy, że mam wiele wątków roboczych, które obsługują zapytania do bazy danych przesyłane do kolejki

#in a long running loop
try:
    query = queue.get()
    conn = connect_to_db(<main db>)
    curs = conn.cursor()
    try:
        curs.execute("<some query on user input that may fail even if sanitized">)
    except DBError:
        logconn = connect_to_db(<logging db>)
        logcurs = logconn.cursor()
        logcurs.execute("<update in DB log with record of failed query")
        logcurs.close()
        logconn.close()
    else:

        #we can't put this in main try block because an error connecting
        #to the logging DB would be indistinguishable from an error in 
        #the mainquery 

        #We can't put this after the whole try: except: finally: block
        #because then we don't know if the query was successful or not

        logconn = connect_to_db(<logging db>)
        logcurs = logconn.cursor()
        logcurs.execute("<update in DB log with record of successful query")
        logcurs.close()
        logconn.close()
        #do something in response to successful query
except DBError:
    #This DBError is because of a problem with the logging database, but 
    #we can't let that crash the whole thread over what might be a
    #temporary network glitch
finally:
    curs.close()
    conn.close()
    #other cleanup if necessary like telling the queue the task is finished

Oczywiście, jeśli możesz rozróżnić możliwe wyjątki, które mogą zostać rzucone, nie musisz tego używać, ale jeśli kod reagujący na udany fragment kodu może rzucić to samo wyjątek jako udany kawałek, i nie można po prostu pozwolić drugi możliwy wyjątek odejść, lub powrócić natychmiast po sukcesie (co zabiłoby wątek w moim przypadku), to się przydaje.

 1
Author: sirlark,
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-11-21 17:22:05

Oto inne miejsce, w którym lubię używać tego wzoru:

 while data in items:
     try
        data = json.loads(data)
     except ValueError as e:
        log error
     else:
        # work on the `data`
 1
Author: Guru Devanla,
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
2015-03-04 00:48:44

Załóżmy, że twoja logika programowania zależy od tego, czy słownik ma wpis z danym kluczem. Możesz przetestować wynik dict.get(key) używając if... else... construct, lub możesz zrobić:

try:
    val = dic[key]
except KeyError:
    do_some_stuff()
else:
    do_some_stuff_with_val()
 1
Author: Gene,
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
2015-04-01 21:05:41

Jednym z możliwych scenariuszy użycia są nieprzewidywalne wyjątki, które można obejść, jeśli spróbujesz ponownie. Na przykład, gdy operacje w bloku try dotyczą liczb losowych:

while True:
    try:
        r = random.random()
        some_operation_that_fails_for_specific_r(r)
    except Exception:
        continue
    else:
        break

Ale jeśli można przewidzieć wyjątek, zawsze należy wybrać walidację wcześniej niż wyjątek. Jednak nie wszystko można przewidzieć, więc ten wzór kodu ma swoje miejsce.

 1
Author: NeoWang,
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-04-13 08:48:14

Znalazłem else przydatne do obsługi prawdopodobnie błędnego pliku konfiguracyjnego:

try:
    value, unit = cfg['lock'].split()
except ValueError:
    msg = 'lock monitoring config must consist of two words separated by white space'
    self.log('warn', msg)
else:
     # get on with lock monitoring if config is ok

Wyjątek odczyt lock config wyłącza monitorowanie blokady i ValueErrors loguje pomocny komunikat ostrzegawczy.

 1
Author: Nick,
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-09-18 23:55:23

Blok else: jest mylący i (prawie) bezużyteczny. Jest również częścią for i while.

Właściwie, nawet na if-oświadczenie, else: może być nadużywane w naprawdę straszny sposób tworząc błędy, które są bardzo trudne do znalezienia.

Rozważ to.
   if a < 10:
       # condition stated explicitly
   elif a > 10 and b < 10:
       # condition confusing but at least explicit
   else:
       # Exactly what is true here?
       # Can be hard to reason out what condition is true

Pomyśl dwa razy o else:. Ogólnie jest to problem. Unikaj tego z wyjątkiem if-oświadczenia i nawet wtedy rozważ udokumentowanie else- warunku, aby było jasne.

 -13
Author: S.Lott,
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
2009-05-13 02:28:03