Frage Manuell eine Exception in Python auslösen (werfen)


Wie kann ich eine Ausnahme in Python auslösen, damit sie später über eine except Block?


1516
2018-01-12 21:07


Ursprung


Antworten:


Wie kann ich manuell eine Ausnahme in Python auslösen / auslösen?

Verwenden Sie den spezifischsten Exception-Konstruktor, der Ihrem Problem semantisch entspricht.

Seien Sie spezifisch in Ihrer Nachricht, z.

raise ValueError('A very specific bad thing happened.')

Generische Ausnahmen nicht auslösen

Vermeiden Sie das Generieren einer generischen Ausnahme. Um es zu fangen, müssen Sie alle anderen spezifischeren Ausnahmen abfangen, die es ableiten.

Problem 1: Fehler verstecken

raise Exception('I know Python!') # Don't! If you catch, likely to hide bugs.

Beispielsweise:

def demo_bad_catch():
    try:
        raise ValueError('Represents a hidden bug, do not catch this')
        raise Exception('This is the exception you expect to handle')
    except Exception as error:
        print('Caught this error: ' + repr(error))

>>> demo_bad_catch()
Caught this error: ValueError('Represents a hidden bug, do not catch this',)

Problem 2: Wird nicht fangen

und spezifischere Fänge fangen die allgemeine Ausnahme nicht ein:

def demo_no_catch():
    try:
        raise Exception('general exceptions not caught by specific handling')
    except ValueError as e:
        print('we will not catch exception: Exception')


>>> demo_no_catch()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in demo_no_catch
Exception: general exceptions not caught by specific handling

Best Practices: raise Erklärung

Verwenden Sie stattdessen den spezifischsten Exception-Konstruktor, der Ihrem Problem semantisch entspricht.

raise ValueError('A very specific bad thing happened')

was natürlich auch zulässt, dass eine beliebige Anzahl von Argumenten an den Konstruktor übergeben wird:

raise ValueError('A very specific bad thing happened', 'foo', 'bar', 'baz') 

Diese Argumente werden von der args Attribut für das Exception-Objekt. Beispielsweise:

try:
    some_code_that_may_raise_our_value_error()
except ValueError as err:
    print(err.args)

Drucke

('message', 'foo', 'bar', 'baz')    

In Python 2.5 ein tatsächlicher message Attribut wurde zu BaseException hinzugefügt, um Benutzer dazu zu ermutigen, Exceptions zu unterklassieren und die Verwendung zu beenden args, aber die Einführung von message und die ursprüngliche Abwertung von Argumenten wurde zurückgezogen.

Best Practices: except Klausel

Wenn Sie sich innerhalb einer except-Klausel befinden, möchten Sie beispielsweise protokollieren, dass ein bestimmter Fehlertyp aufgetreten ist, und dann erneut erhöhen. Der beste Weg dies zu tun, während der Stack-Trace beibehalten wird, ist eine bloße Raise-Anweisung. Beispielsweise:

logger = logging.getLogger(__name__)

try:
    do_something_in_app_that_breaks_easily()
except AppError as error:
    logger.error(error)
    raise                 # just this!
    # raise AppError      # Don't do this, you'll lose the stack trace!

Ändere deine Fehler nicht ... aber wenn du darauf bestehst.

Sie können den Stacktrace (und den Fehlerwert) mit beibehalten sys.exc_info(), aber das ist viel fehleranfälliger und hat Kompatibilitätsprobleme zwischen Python 2 und 3, lieber ein blankes verwenden raise neu zu erhöhen.

Zu erklären - das sys.exc_info() gibt den Typ, Wert und Traceback zurück.

type, value, traceback = sys.exc_info()

Dies ist die Syntax in Python 2 - Beachten Sie, dass dies nicht mit Python 3 kompatibel ist:

    raise AppError, error, sys.exc_info()[2] # avoid this.
    # Equivalently, as error *is* the second object:
    raise sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]

Wenn Sie möchten, können Sie ändern, was mit Ihrer neuen Gehaltserhöhung geschieht - z. neue Argumente für die Instanz setzen:

def error():
    raise ValueError('oops!')

def catch_error_modify_message():
    try:
        error()
    except ValueError:
        error_type, error_instance, traceback = sys.exc_info()
        error_instance.args = (error_instance.args[0] + ' <modification>',)
        raise error_type, error_instance, traceback

Und wir haben den gesamten Traceback beibehalten, während wir die Argumente geändert haben. Beachten Sie, dass dies ist keine gute Praxis und es ist ungültiger Satzbau in Python 3 (wodurch die Kompatibilität wesentlich erschwert wird).

>>> catch_error_modify_message()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in catch_error_modify_message
  File "<stdin>", line 2, in error
ValueError: oops! <modification>

Im Python 3:

    raise error.with_traceback(sys.exc_info()[2])

Nochmals: Vermeiden Sie die manuelle Manipulation von Trace-Backs. Es ist weniger effizient und mehr fehleranfällig. Und wenn Sie Threading und sys.exc_info Sie können sogar die falsche Rückverfolgung erhalten (besonders, wenn Sie die Ausnahmebehandlung für den Kontrollfluss verwenden - was ich persönlich eher vermeiden würde.)

Python 3, Ausnahmeverkettung

In Python 3 können Sie Exceptions ketten, die Tracebacks beibehalten:

    raise RuntimeError('specific message') from error

Sei vorsichtig:

  • Dies tut Erlaube es, den erhöhten Fehlertyp zu ändern und
  • das ist nicht kompatibel mit Python 2.

Veraltete Methoden:

Diese können sich leicht verstecken und sogar in den Produktionscode gelangen. Sie möchten eine Ausnahme auslösen, und wenn Sie dies tun, wird eine Ausnahme ausgelöst. aber nicht der eine beabsichtigt!

Gültig in Python 2, aber nicht in Python 3 ist das Folgende:

raise ValueError, 'message' # Don't do this, it's deprecated!

Nur gültig in viel älteren Versionen von Python (2.4 und niedriger), können Sie immer noch Leute sehen, die Saiten anheben:

raise 'message' # really really wrong. don't do this.

In allen modernen Versionen wird dadurch ein TypeError ausgelöst, weil Sie keinen BaseException-Typ auslösen. Wenn Sie nicht nach der richtigen Ausnahme suchen und nicht über einen Prüfer verfügen, der das Problem erkennt, könnte es in Produktion gehen.

Beispiel Verwendung

Ich rufe Exceptions ab, um Nutzer über meine API zu warnen, wenn sie sie falsch verwenden:

def api_func(foo):
    '''foo should be either 'baz' or 'bar'. returns something very useful.'''
    if foo not in _ALLOWED_ARGS:
        raise ValueError('{foo} wrong, use "baz" or "bar"'.format(foo=repr(foo)))

Erstellen Sie bei Bedarf eigene Fehlertypen

"Ich möchte absichtlich einen Fehler machen, so dass es in die Ausnahme gehen würde"

Sie können eigene Fehlertypen erstellen, wenn Sie angeben möchten, dass etwas mit Ihrer Anwendung nicht stimmt. Unterordnen Sie einfach den entsprechenden Punkt in der Ausnahmehierarchie:

class MyAppLookupError(LookupError):
    '''raise this when there's a lookup error for my app'''

und Verwendung:

if important_key not in resource_dict and not ok_to_be_missing:
    raise MyAppLookupError('resource is missing, and that is not ok.')

1890
2018-06-05 16:30



Tu das NICHT. Nackt werden Exception ist absolut nicht das richtige tun; sehen Aaron Halls ausgezeichnete Antwort stattdessen.

Ich kann nicht viel mehr Python als das bekommen:

raise Exception("I know python!")

Sehen die Raise-Anweisung Dokumente Für Python, wenn Sie weitere Informationen wünschen.


541
2018-01-12 21:08



Für den häufigen Fall, in dem Sie eine Exception als Reaktion auf unerwartete Bedingungen auslösen müssen und die Sie niemals abfangen möchten, sondern einfach schnell ausfällt, damit Sie von dort aus debuggen können, wenn es jemals passiert - das logischste scheint es zu sein AssertionError:

if 0 < distance <= RADIUS:
    #Do something.
elif RADIUS < distance:
    #Do something.
else:
    raise AssertionError("Unexpected value of 'distance'!", distance)

29
2018-05-19 04:55



In Python3 gibt es 4 verschiedene Syntaxen für das Aufrufen von Ausnahmen:

1. raise exception 
2. raise exception (args) 
3. raise
4. raise exception (args) from original_exception

1. Raise Exception gegen 2. Raise Exception (Args)

Wenn du benutzt raise exception (args)  eine Ausnahme machen dann die args wird gedruckt, wenn Sie das Ausnahmeobjekt drucken - wie im folgenden Beispiel gezeigt.

  #raise exception (args)
    try:
        raise ValueError("I have raised an Exception")
    except ValueError as exp:
        print ("Error", exp)     # Output -> Error I have raised an Exception 



  #raise execption 
    try:
        raise ValueError
    except ValueError as exp:
        print ("Error", exp)     # Output -> Error 

3. Erhöhung

raise Eine Anweisung ohne Argumente hebt die letzte Ausnahme erneut auf. Dies ist nützlich, wenn Sie einige Aktionen ausführen müssen, nachdem Sie die Ausnahme abgefangen haben und sie dann erneut auslösen möchten. Aber wenn es vorher keine Ausnahme gab, raise Aussage erhebt sich TypeError Ausnahme.

def somefunction():
    print("some cleaning")

a=10
b=0 
result=None

try:
    result=a/b
    print(result)

except Exception:            #Output ->
    somefunction()           #some cleaning
    raise                    #Traceback (most recent call last):
                             #File "python", line 8, in <module>
                             #ZeroDivisionError: division by zero

4. Exception (args) von original_exception auslösen

Diese Anweisung wird zum Erstellen einer Ausnahmekette verwendet, bei der eine Ausnahme, die als Reaktion auf eine andere Ausnahme ausgelöst wird, die Details der ursprünglichen Ausnahme enthalten kann (siehe Beispiel unten).

class MyCustomException(Exception):
pass

a=10
b=0 
reuslt=None
try:
    try:
        result=a/b

    except ZeroDivisionError as exp:
        print("ZeroDivisionError -- ",exp)
        raise MyCustomException("Zero Division ") from exp

except MyCustomException as exp:
        print("MyException",exp)
        print(exp.__cause__)

Ausgabe:

ZeroDivisionError --  division by zero
MyException Zero Division 
division by zero

22
2017-11-08 17:54



Lesen Sie zuerst die vorhandenen Antworten, dies ist nur ein Addendum.

Beachten Sie, dass Sie Ausnahmen mit oder ohne Argumente auslösen können.

Beispiel:

raise SystemExit

beendet das Programm, aber Sie möchten wissen, was passiert ist.So können Sie dies verwenden.

raise SystemExit("program exited")

Dies wird "Programm beendet" an stderr vor dem Schließen des Programms drucken.


5
2018-03-29 11:59