"Richtige Möglichkeit, benutzerdefinierte Ausnahmen in modernem Python zu deklarieren?"
Dies ist in Ordnung, es sei denn, Ihre Ausnahme ist wirklich eine Art spezifischere Ausnahme:
class MyException(Exception):
pass
Oder besser (vielleicht perfekt), anstatt pass
einen Docstring zu geben:
class MyException(Exception):
"""Raise for my specific kind of exception"""
Unterklassen Ausnahme Unterklassen
Aus den Dokumenten
Exception
Alle integrierten, nicht systemexitierenden Ausnahmen werden von dieser Klasse abgeleitet. Alle benutzerdefinierten Ausnahmen sollten ebenfalls von dieser Klasse abgeleitet werden.
Das heißt, wenn Ihre Ausnahme ein Typ einer spezifischeren Ausnahme ist, klassifizieren Sie diese Ausnahme anstelle der generischen Exception
(und das Ergebnis ist, dass Sie immer noch davon ableiten, Exception
wie in den Dokumenten empfohlen). Sie können auch mindestens eine Dokumentzeichenfolge angeben (und nicht gezwungen sein, das pass
Schlüsselwort zu verwenden):
class MyAppValueError(ValueError):
'''Raise when my specific value is wrong'''
Legen Sie Attribute fest, die Sie selbst mit einem benutzerdefinierten erstellen __init__
. Vermeiden Sie es, ein Diktat als Positionsargument zu übergeben. Zukünftige Benutzer Ihres Codes werden es Ihnen danken. Wenn Sie das veraltete Nachrichtenattribut verwenden, wird durch die Zuweisung selbst Folgendes vermieden DeprecationWarning
:
class MyAppValueError(ValueError):
'''Raise when a specific subset of values in context of app is wrong'''
def __init__(self, message, foo, *args):
self.message = message # without this you may get DeprecationWarning
# Special attribute you desire with your Error,
# perhaps the value that caused the error?:
self.foo = foo
# allow users initialize misc. arguments as any other builtin Error
super(MyAppValueError, self).__init__(message, foo, *args)
Es ist wirklich nicht nötig, eigene __str__
oder zu schreiben __repr__
. Die eingebauten sind sehr nett und Ihre kooperative Vererbung stellt sicher, dass Sie sie verwenden.
Kritik der Top-Antwort
Vielleicht habe ich die Frage verpasst, aber warum nicht:
class MyException(Exception):
pass
Wiederum besteht das Problem mit dem oben Gesagten darin, dass Sie es entweder spezifisch benennen müssen (importieren, wenn es an anderer Stelle erstellt wurde) oder Ausnahme abfangen müssen, um es abzufangen (aber Sie sind wahrscheinlich nicht bereit, alle Arten von Ausnahmen zu behandeln). und Sie sollten nur Ausnahmen abfangen, für die Sie bereit sind). Ähnliche Kritik wie unten, aber zusätzlich ist dies nicht die Möglichkeit, über zu initialisieren super
, und Sie erhalten eine, DeprecationWarning
wenn Sie auf das Nachrichtenattribut zugreifen:
Bearbeiten: Um etwas zu überschreiben (oder zusätzliche Argumente zu übergeben), gehen Sie folgendermaßen vor:
class ValidationError(Exception):
def __init__(self, message, errors):
# Call the base class constructor with the parameters it needs
super(ValidationError, self).__init__(message)
# Now for your custom code...
self.errors = errors
Auf diese Weise können Sie Fehlermeldungen an den zweiten Parameter übergeben und später mit e.errors darauf zugreifen
Außerdem müssen genau zwei Argumente (abgesehen von self
) übergeben werden. Nicht mehr und nicht weniger. Dies ist eine interessante Einschränkung, die zukünftige Benutzer möglicherweise nicht zu schätzen wissen.
Direkt zu sein - es verletzt die Substituierbarkeit von Liskov .
Ich werde beide Fehler demonstrieren:
>>> ValidationError('foo', 'bar', 'baz').message
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
ValidationError('foo', 'bar', 'baz').message
TypeError: __init__() takes exactly 3 arguments (4 given)
>>> ValidationError('foo', 'bar').message
__main__:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
'foo'
Verglichen mit:
>>> MyAppValueError('foo', 'FOO', 'bar').message
'foo'