1827 Stimmen

Der richtige Weg, um benutzerdefinierte Ausnahmen in modernen Python deklarieren?

Was ist der richtige Weg, um benutzerdefinierte Ausnahmeklassen in modernem Python zu deklarieren? Mein primäres Ziel ist es, zu folgen, was auch immer Standard andere Ausnahmeklassen haben, so dass (zum Beispiel) jede zusätzliche Zeichenfolge, die ich in der Ausnahme enthalten ist, von was auch immer Werkzeug die Ausnahme gefangen gedruckt.

Unter "modernem Python" verstehe ich etwas, das in Python 2.5 läuft, aber für Python 2.6 und Python 3.* "korrekt" ist. Und mit "benutzerdefiniert" meine ich eine Exception Objekt, das zusätzliche Daten über die Ursache des Fehlers enthalten kann: eine Zeichenkette, vielleicht auch ein anderes beliebiges Objekt, das für die Ausnahme relevant ist.

Ich wurde durch die folgende Verwerfungswarnung in Python 2.6.2 gestolpert:

>>> class MyError(Exception):
...     def __init__(self, message):
...         self.message = message
... 
>>> MyError("foo")
_sandbox.py:3: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6

Es scheint verrückt, dass BaseException hat eine besondere Bedeutung für Attribute mit dem Namen message . Ich entnehme PEP-352 dieses Attribut hatte in 2.5 eine besondere Bedeutung, die jetzt abgeschafft werden soll, also ist dieser Name (und nur dieser) jetzt wohl verboten? Pfui.

Ich bin mir auch unscharf bewusst, dass Exception hat einen magischen Parameter args aber ich habe nie gewusst, wie man es benutzt. Ich bin mir auch nicht sicher, ob es der richtige Weg ist, die Dinge in Zukunft zu tun; viele der Diskussionen, die ich online gefunden habe, deuten darauf hin, dass sie versuchen, args in Python 3 abzuschaffen.

Update: zwei Antworten haben vorgeschlagen, die __init__ y __str__ / __unicode__ / __repr__ . Das scheint eine Menge Tipparbeit zu sein, ist das notwendig?

4voto

omkaartg Punkte 2498

Versuchen Sie dieses Beispiel

class InvalidInputError(Exception):
    def __init__(self, msg):
        self.msg = msg
    def __str__(self):
        return repr(self.msg)

inp = int(input("Enter a number between 1 to 10:"))
try:
    if type(inp) != int or inp not in list(range(1,11)):
        raise InvalidInputError
except InvalidInputError:
    print("Invalid input entered")

4voto

Macintosh Fan Punkte 310

Ein wirklich einfacher Ansatz:

class CustomError(Exception):
    pass

raise CustomError("Hmm, seems like this was custom coded...")

Oder lassen Sie den Fehler ohne Druck ausgeben __main__ (kann sauberer und ordentlicher aussehen):

class CustomError(Exception):
    __module__ = Exception.__module__

raise CustomError("Improved CustomError!")

1voto

Francis Cagney Punkte 153

Ich bin auf dieses Thema gestoßen. Dies ist, wie ich benutzerdefinierte Ausnahmen zu tun. Während die Fault Klasse etwas komplex ist, macht sie die Deklaration von benutzerdefinierten, ausdrucksstarken Ausnahmen mit variablen Argumenten trivial.

FinalViolation , SingletonViolation sind beide Unterklassen von TypeError so wird Code unten gefangen werden.

try:
    <do something>
except TypeError as ex:
    <handler>

Deshalb ist Fault erbt nicht von Exception . Damit abgeleitete Ausnahmen von der Ausnahme ihrer Wahl erben können.

class Fault:
    """Generic Exception base class. Note not descendant of Exception
Inheriting exceptions override formats"""
    formats = '' # to be overriden in descendant classes

    def __init__(self, *args):
        """Just save args for __str__"""
        self.args = args

    def __str__(self):
        """Use formats declared in descendant classes, and saved args to build exception text"""
        return self.formats.format(*self.args)

class TypeFault(Fault, TypeError):
    """Helper class mixing Fault and TypeError"""

class FinalViolation(TypeFault):
    """Custom exception raised if inheriting from 'final' class"""
    formats = "type {} is not an acceptable base type. It cannot be inherited from."

class SingletonViolation(TypeFault):     
    """Custom exception raised if instancing 'singleton' class a second time"""
    formats = "type {} is a singleton. It can only be instanced once."

FinalViolation , SingletonViolation leider nur 1 Argument akzeptieren.

Man könnte aber leicht einen Multi-Arg-Fehler erzeugen, z.B.

class VesselLoadingError(Fault, BufferError):
    formats = "My {} is full of {}."

raise VesselLoadingError('hovercraft', 'eels')

__main__.VesselLoadingError: My hovercraft is full of eels.

-2voto

Für mich ist es einfach __init__ und Variablen, sondern machen manchmal Tests.

Meine Probe:

Error_codes = { 100: "Not enough parameters", 101: "Number of special characters more than limits", 102: "At least 18 alphanumeric characters and list of special chars !@#$&*" }

class localbreak( Exception ) :
    Message = ""

    def __init__(self, Message):
        self.Message = Message
        return
    def __str__(self):
        print(self.Message)
        return "False"

### When calling ...
raise localbreak(Error_codes[102])

Ausgabe:

Traceback (most recent call last):   File "ASCII.py", line 150, in <module>
    main(OldPassword, Newpassword)   File "ASCII.py", line 39, in main
    result = read_input("1", "2", Newpassword, "4")                                     
    File "ASCII.py", line 69, in read_input
    raise localbreak(Error_codes[102]) At least 18 alphanumeric characters and list of special chars !@#$&*
__main__.localbreak: False

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X