Suche…


Einführung

Fehler, die während der Ausführung erkannt werden, werden als Ausnahmen bezeichnet und sind nicht unbedingt tödlich. Die meisten Ausnahmen werden nicht von Programmen behandelt. Es ist möglich, Programme zu schreiben, die ausgewählte Ausnahmen behandeln. Es gibt bestimmte Funktionen in Python, um Ausnahmen und Ausnahmelogik zu behandeln. Außerdem haben Ausnahmen eine reichhaltige BaseException , die alle vom BaseException Typ erben.

Syntax

  • Ausnahme auslösen
  • # erhöhen eine Ausnahme, die bereits ausgelöst wurde
  • Ausnahme von Ursache auslösen # Python 3 - Ausnahmeursache festlegen
  • Ausnahme von None auslösen # Python 3 - unterdrückt den gesamten Ausnahmekontext
  • Versuchen:
  • außer [Ausnahmetypen] [ als Bezeichner ] :
  • sonst:
  • endlich:

Ausnahmen aufwerfen

Wenn Ihr Code auf eine Bedingung stößt, mit der er nicht umgehen kann, beispielsweise ein falscher Parameter, sollte die entsprechende Ausnahme ausgelöst werden.

def even_the_odds(odds):
    if odds % 2 != 1:
        raise ValueError("Did not get an odd number")
    
    return odds + 1

Ausnahmen fangen

Verwenden Sie try...except: um Ausnahmen abzufangen. Sie sollten so genau wie möglich eine Ausnahme angeben:

try:
    x = 5 / 0
except ZeroDivisionError as e:
    # `e` is the exception object
    print("Got a divide by zero! The exception was:", e)
    # handle exceptional case
    x = 0  
finally:
    print "The END"
    # it runs no matter what execute.

Die angegebene Ausnahmeklasse - in diesem Fall ZeroDivisionError - ZeroDivisionError alle Ausnahmen, die dieser Klasse oder einer Unterklasse dieser Ausnahmebedingung angehören.

ZeroDivisionError ist beispielsweise eine Unterklasse von ArithmeticError :

>>> ZeroDivisionError.__bases__
(<class 'ArithmeticError'>,)

Das Folgende wird also immer noch den ZeroDivisionError fangen:

try:
    5 / 0
except ArithmeticError:
    print("Got arithmetic error")

Ausführen von Bereinigungscode mit

Manchmal möchten Sie möglicherweise, dass unabhängig von der aufgetretenen Ausnahme etwas geschieht, beispielsweise wenn Sie einige Ressourcen bereinigen müssen.

Der finally Block einer try Klausel wird unabhängig davon ausgeführt, ob Ausnahmen ausgelöst wurden.

resource = allocate_some_expensive_resource()
try:
    do_stuff(resource)
except SomeException as e:
    log_error(e)
    raise  # re-raise the error
finally:
    free_expensive_resource(resource)

Dieses Muster wird mit Kontextmanagern (mit der Anweisung with ) oft besser behandelt.

Ausnahmen erneut erhöhen

Manchmal möchten Sie eine Ausnahme erfassen, um sie zu prüfen, z. B. zu Protokollierungszwecken. Nach der Inspektion möchten Sie, dass die Ausnahme wie zuvor weitergegeben wird.

Verwenden Sie in diesem Fall einfach die raise Anweisung ohne Parameter.

try:
    5 / 0
except ZeroDivisionError:
    print("Got an error")
    raise

Beachten Sie jedoch, dass jemand weiter oben im Aufrufer-Stack die Ausnahme noch fangen und irgendwie damit umgehen kann. Die fertige Ausgabe kann in diesem Fall ein Ärgernis sein, da dies auf jeden Fall passieren wird (gefangen oder nicht gefangen). Daher empfiehlt es sich, eine andere Ausnahme auszulösen, die Ihren Kommentar zur Situation sowie die ursprüngliche Ausnahme enthält:

try:
    5 / 0
except ZeroDivisionError as e:
    raise ZeroDivisionError("Got an error", e)

Dies hat jedoch den Nachteil, dass die Ausnahmespur auf genau diese raise reduziert wird raise während die raise ohne Argument die ursprüngliche Ausnahmespur beibehält.

In Python 3 können Sie den ursprünglichen Stapel beibehalten, indem Sie die raise - from - Syntax verwenden:

    raise ZeroDivisionError("Got an error") from e

Kettenausnahmen mit Raise from

Bei der Behandlung einer Ausnahme können Sie eine weitere Ausnahme auslösen. Wenn Sie IOError beim Lesen aus einer Datei einen IOError , möchten Sie möglicherweise einen anwendungsspezifischen Fehler IOError , der stattdessen den Benutzern Ihrer Bibliothek angezeigt wird.

Python 3.x 3.0

Sie können Ausnahmen verketten, um zu zeigen, wie die Behandlung von Ausnahmen abläuft:

>>> try:
    5 / 0
except ZeroDivisionError as e:
    raise ValueError("Division failed") from e

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
ValueError: Division failed

Ausnahmehierarchie

Die Ausnahmebehandlung erfolgt basierend auf einer Ausnahmehierarchie, die durch die Vererbungsstruktur der Ausnahmeklassen bestimmt wird.

Beispielsweise sind IOError und OSError beide Unterklassen von EnvironmentError . Code, der einen IOError , fängt keinen OSError . Code, der einen EnvironmentError IOError , fängt jedoch sowohl IOError als auch OSError s ab.

Die Hierarchie der integrierten Ausnahmen:

Python 2.x 2.3
BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
      |    +-- ImportError
      |    +-- LookupError
      |    |    +-- IndexError
      |    |    +-- KeyError
      |    +-- MemoryError
      |    +-- NameError
      |    |    +-- UnboundLocalError
      |    +-- ReferenceError
      |    +-- RuntimeError
      |    |    +-- NotImplementedError
      |    +-- SyntaxError
      |    |    +-- IndentationError
      |    |         +-- TabError
      |    +-- SystemError
      |    +-- TypeError
      |    +-- ValueError
      |         +-- UnicodeError
      |              +-- UnicodeDecodeError
      |              +-- UnicodeEncodeError
      |              +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
       +-- ImportWarning
       +-- UnicodeWarning
       +-- BytesWarning
Python 3.x 3.0
BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StopAsyncIteration
      +-- ArithmeticError
      |    +-- FloatingPointError
      |    +-- OverflowError
      |    +-- ZeroDivisionError
      +-- AssertionError
      +-- AttributeError
      +-- BufferError
      +-- EOFError
      +-- ImportError
      +-- LookupError
      |    +-- IndexError
      |    +-- KeyError
      +-- MemoryError
      +-- NameError
      |    +-- UnboundLocalError
      +-- OSError
      |    +-- BlockingIOError
      |    +-- ChildProcessError
      |    +-- ConnectionError
      |    |    +-- BrokenPipeError
      |    |    +-- ConnectionAbortedError
      |    |    +-- ConnectionRefusedError
      |    |    +-- ConnectionResetError
      |    +-- FileExistsError
      |    +-- FileNotFoundError
      |    +-- InterruptedError
      |    +-- IsADirectoryError
      |    +-- NotADirectoryError
      |    +-- PermissionError
      |    +-- ProcessLookupError
      |    +-- TimeoutError
      +-- ReferenceError
      +-- RuntimeError
      |    +-- NotImplementedError
      |    +-- RecursionError
      +-- SyntaxError
      |    +-- IndentationError
      |         +-- TabError
      +-- SystemError
      +-- TypeError
      +-- ValueError
      |    +-- UnicodeError
      |         +-- UnicodeDecodeError
      |         +-- UnicodeEncodeError
      |         +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
           +-- ImportWarning
           +-- UnicodeWarning
           +-- BytesWarning
           +-- ResourceWarning

Ausnahmen sind auch Objekte

Ausnahmen sind nur reguläre Python-Objekte, die von der integrierten BaseException erben. Ein Python-Skript kann die Anweisung raise verwenden, raise Ausführung zu unterbrechen, sodass Python an diesem Punkt einen Stack-Trace des Aufrufstapels und eine Darstellung der Ausnahmeinstanz ausgibt. Zum Beispiel:

>>> def failing_function():
...     raise ValueError('Example error!')
>>> failing_function()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in failing_function
ValueError: Example error!

was besagt, dass ein ValueError mit der Meldung 'Example error!' wurde durch unsere failing_function() , die im Interpreter ausgeführt wurde.

Anrufcode kann beliebige Ausnahmen aller Art behandeln, die ein Anruf auslösen kann:

>>> try:
...     failing_function()
... except ValueError:
...     print('Handled the error')
Handled the error

Sie können halten , die Ausnahme - Objekte erhalten , indem sie in der Zuordnung except... Teil des Ausnahmebehandlung Code:

>>> try:
...     failing_function()
... except ValueError as e:
...     print('Caught exception', repr(e))
Caught exception ValueError('Example error!',)

Eine vollständige Liste der integrierten Python-Ausnahmen mit ihren Beschreibungen finden Sie in der Python-Dokumentation: https://docs.python.org/3.5/library/exceptions.html . Und hier ist die vollständige Liste hierarchisch angeordnet: Ausnahmehierarchie .

Benutzerdefinierte Ausnahmetypen erstellen

Erstellen Sie eine Klasse, die von Exception erbt:

class FooException(Exception):
    pass
try:
    raise FooException("insert description here")
except FooException:
    print("A FooException was raised.")

oder ein anderer Ausnahmetyp:

class NegativeError(ValueError):
      pass

def foo(x):
    # function that only accepts positive values of x
    if x < 0:
        raise NegativeError("Cannot process negative numbers")
    ...  # rest of function body
try:
    result = foo(int(input("Enter a positive integer: ")))  # raw_input in Python 2.x
except NegativeError:
    print("You entered a negative number!")
else:
    print("The result was " + str(result))

Fangen Sie nicht alles!

Während es oft versucht ist, jede Exception zu fangen:

try:
    very_difficult_function()
except Exception:
    # log / try to reconnect / exit gratiously
finally:
    print "The END"
    # it runs no matter what execute.

Oder sogar alles (dazu gehören BaseException und alle BaseException einschließlich Exception ):

try:
    even_more_difficult_function()
except:
    pass  # do whatever needed

In den meisten Fällen ist es eine schlechte Praxis. Es könnte mehr als beabsichtigt sein, z. B. SystemExit , KeyboardInterrupt und MemoryError Jeder sollte im Allgemeinen anders behandelt werden als MemoryError System- oder Logikfehler. Dies bedeutet auch, dass es kein klares Verständnis dafür gibt, was der interne Code falsch machen kann und wie er sich von diesem Zustand richtig erholen kann. Wenn Sie jeden Fehler feststellen, wissen Sie nicht, welcher Fehler aufgetreten ist oder wie er zu beheben ist.

Dies wird häufiger als "Bug Masking" bezeichnet und sollte vermieden werden. Lassen Sie Ihr Programm abstürzen, anstatt im Hintergrund zu versagen oder gar zu verschlimmern, und zwar auf einer tieferen Ausführungsebene. (Stellen Sie sich vor, es ist ein Transaktionssystem)

Normalerweise werden diese Konstrukte auf der äußersten Ebene des Programms verwendet und protokollieren die Details des Fehlers, sodass der Fehler behoben werden kann oder der Fehler genauer behandelt werden kann.

Mehrere Ausnahmen abfangen

Es gibt mehrere Möglichkeiten, mehrere Ausnahmen abzufangen .

Die erste besteht darin, ein Tupel der Ausnahmetypen zu erstellen, die auf dieselbe Weise abgefangen und behandelt werden sollen. In diesem Beispiel ignoriert der Code die Ausnahmen KeyError und AttributeError .

try:
    d = {}
    a = d[1]
    b = d.non_existing_field
except (KeyError, AttributeError) as e:
    print("A KeyError or an AttributeError exception has been caught.")

Wenn Sie unterschiedliche Ausnahmen auf unterschiedliche Weise behandeln möchten, können Sie für jeden Typ einen eigenen Ausnahmeblock bereitstellen. In diesem Beispiel fangen wir immer noch KeyError und AttributeError , behandeln die Ausnahmen jedoch auf unterschiedliche Weise.

try:
    d = {}
    a = d[1]
    b = d.non_existing_field
except KeyError as e:
    print("A KeyError has occurred. Exception message:", e)
except AttributeError as e:
    print("An AttributeError has occurred. Exception message:", e)

Praktische Beispiele für die Behandlung von Ausnahmen

Benutzereingabe

Stellen Sie sich vor, Sie möchten, dass ein Benutzer über die Eingabe eine Nummer input . Sie möchten sicherstellen, dass die Eingabe eine Zahl ist. Sie können try / mit except davon verwenden:

Python 3.x 3.0
while True:
    try:
        nb = int(input('Enter a number: '))
        break
    except ValueError:
        print('This is not a number, try again.')

Hinweis: Python 2.x verwendet stattdessen raw_input . die Funktion input existiert in Python 2.x hat aber eine andere Semantik. Im obigen Beispiel würde die input auch Ausdrücke wie 2 + 2 akzeptieren, die eine Zahl ergeben.

Wenn die Eingabe nicht in eine Ganzzahl konvertiert werden konnte, wird ein ValueError . Sie können es mit except fangen. Wenn keine Ausnahme ausgelöst wird break springt break aus der Schleife. Nach der Schleife enthält nb eine ganze Zahl.

Wörterbücher

Stellen Sie sich über eine Liste von aufeinanderfolgenden ganzen Zahlen iterieren, wie range(n) , und Sie haben eine Liste der Wörterbücher d , die Informationen über die Dinge enthält zu tun , wenn Sie einige bestimmte ganze Zahlen auftreten, sagen die überspringen d[i] Nächsten.

d = [{7: 3}, {25: 9}, {38: 5}]

for i in range(len(d)):
    do_stuff(i)
    try:
       dic = d[i]
       i += dic[i]
    except KeyError:
       i += 1

Ein KeyError wird KeyError , wenn Sie versuchen, einen Wert aus einem Wörterbuch für einen nicht vorhandenen Schlüssel KeyError .

Sonst

Code in einem else-Block wird nur ausgeführt, wenn vom Code im try Block keine Ausnahmen ausgelöst wurden. Dies ist nützlich, wenn Sie Code haben, den Sie nicht ausführen möchten, wenn eine Ausnahme ausgelöst wird. Sie möchten jedoch nicht, dass durch diesen Code ausgelöste Ausnahmen abgefangen werden.

Zum Beispiel:

try:
    data = {1: 'one', 2: 'two'}
    print(data[1])
except KeyError as e:
    print('key not found')
else:
    raise ValueError()
# Output: one
# Output: ValueError

Beachten Sie, dass diese Art von else: nicht mit einer if -Klausel zu einem elif . Wenn Sie Folgendes haben, if es unter dem else: eingerückt bleiben muss:

try:
    ...
except ...:
    ...
else:
    if ...:
        ...
    elif ...:
        ...
    else:
        ...


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow