812 Stimmen

Welche Ausnahme sollte ich auf schlechte/illegale Argumentkombinationen in Python auslösen?

Ich habe mich über die besten Praktiken für die Anzeige von ungültigen Argumentkombinationen in Python gewundert. Ich habe über ein paar Situationen kommen, wo Sie eine Funktion wie so haben:

def import_to_orm(name, save=False, recurse=False):
    """
    :param name: Name of some external entity to import.
    :param save: Save the ORM object before returning.
    :param recurse: Attempt to import associated objects as well. Because you
        need the original object to have a key to relate to, save must be
        `True` for recurse to be `True`.
    :raise BadValueError: If `recurse and not save`.
    :return: The ORM object.
    """
    pass

Das einzige Ärgernis dabei ist, dass jedes Paket seine eigene, meist leicht abweichende BadValueError . Ich weiß, dass es in Java Folgendes gibt java.lang.IllegalArgumentException -- ist es klar, dass jeder seine eigene Website erstellen wird BadValueError s in Python oder gibt es eine andere, bevorzugte Methode?

890voto

dbr Punkte 158949

Ich würde einfach erhöhen WertFehler es sei denn, Sie benötigen eine genauere Ausnahme

def import_to_orm(name, save=False, recurse=False):
    if recurse and not save:
        raise ValueError("save must be True if recurse is True")

Es hat wirklich keinen Sinn, das zu tun. class BadValueError(ValueError):pass - Ihre benutzerdefinierte Klasse ist in der Verwendung identisch mit WertFehler Warum sollte man das also nicht nutzen?

121 Stimmen

> "Warum also nicht das verwenden?" - Spezifität. Vielleicht möchte ich auf einer äußeren Ebene "MyValueError" abfangen, aber nicht alle "ValueError".

8 Stimmen

Ja, ein Teil der Frage nach der Spezifität ist also, wo sonst ValueError ausgelöst wird. Wenn die aufgerufene Funktion Ihre Argumente mag, aber intern math.sqrt(-1) aufruft, kann ein Aufrufer ValueError abfangen und erwarten, dass seine Argumente unangemessen waren. Vielleicht überprüfen Sie in diesem Fall einfach die Nachricht...

4 Stimmen

Ich bin mir nicht sicher, ob dieses Argument zutrifft: Wenn jemand die math.sqrt(-1) Das ist ein Programmierfehler, der auf jeden Fall behoben werden muss. ValueError ist nicht dazu bestimmt, bei der normalen Programmausführung abgefangen zu werden, sonst würde sie sich aus RuntimeError .

147voto

Markus Jarderot Punkte 83090

Ich würde erben von ValueError

class IllegalArgumentError(ValueError):
    pass

Manchmal ist es besser, eigene Ausnahmen zu erstellen, aber von einer eingebauten Ausnahme zu erben, die dem, was Sie wollen, so nahe wie möglich kommt.

Wenn Sie diesen spezifischen Fehler abfangen müssen, ist es hilfreich, einen Namen zu haben.

39 Stimmen

Keine Klassen und benutzerdefinierten Ausnahmen mehr schreiben - pyvideo.org/video/880/stop-writing-classes

86 Stimmen

@HamishGrubijan das Video ist schrecklich. Wenn jemand eine gute Verwendung für eine Klasse vorschlägt, blökt er nur: "Benutzt keine Klassen." Brillant. Klassen sind gut. Aber glauben Sie nicht, dass ich es sage .

17 Stimmen

@RobertGrant Nein, du verstehst es nicht. In diesem Video geht es nicht wirklich darum, wörtlich "keine Klassen zu verwenden". Es geht darum, die Dinge nicht zu kompliziert zu machen.

50voto

J Bones Punkte 515

Ich denke, der beste Weg, dies zu behandeln ist die Art und Weise Python selbst behandelt es. Python löst einen TypeError aus. Zum Beispiel:

$ python -c 'print(sum())'
Traceback (most recent call last):
File "<string>", line 1, in <module>
TypeError: sum expected at least 1 arguments, got 0

Unser Junior-Entwickler hat diese Seite gerade bei einer Google-Suche nach "python exception wrong arguments" gefunden und ich bin überrascht, dass die offensichtliche (für mich) Antwort in den zehn Jahren, seit diese Frage gestellt wurde, nicht vorgeschlagen wurde.

19 Stimmen

Nichts überrascht mich, aber ich stimme 100% zu, dass TypeError die richtige Ausnahme ist, wenn der Typ auf einige der Argumente in die Funktion übergeben falsch ist. Ein ValueError wäre geeignet, wenn die Variablen vom richtigen Typ sind, aber ihr Inhalt und ihre Werte keinen Sinn ergeben.

0 Stimmen

Ich denke, dass es hier wahrscheinlich um fehlende oder unaufgeforderte Argumente geht, während es in der Frage um Argumente geht, die zwar korrekt angegeben werden, aber auf einer höheren Abstraktionsebene falsch sind, die den Wert des angegebenen Arguments. Aber da ich eigentlich nach ersterem gesucht habe, gibt es trotzdem ein Upvote.

5 Stimmen

Wie @user3504575 und @Nobody sagten, wird TypeError verwendet, wenn die Argumente nicht mit der Funktionssignatur übereinstimmen (falsche Anzahl von Positionsargumenten, Schlüsselwortargumente mit falschem Namen, falscher Argumenttyp), aber ein ValueError wird verwendet, wenn der Funktionsaufruf mit der Signatur übereinstimmt, aber die Argumentwerte ungültig sind (z. B. beim Aufruf von int('a') ). Quelle

39voto

Gloweye Punkte 1151

Es kommt darauf an, was das Problem mit den Argumenten ist.

Wenn das Argument den falschen Typ hat, wird ein TypeError ausgelöst. Zum Beispiel, wenn Sie eine Zeichenkette anstelle eines dieser Booleans erhalten.

if not isinstance(save, bool):
    raise TypeError(f"Argument save must be of type bool, not {type(save)}")

Beachten Sie jedoch, dass wir in Python selten solche Überprüfungen durchführen. Wenn das Argument wirklich ungültig ist, wird sich wahrscheinlich eine tiefere Funktion für uns beschweren. Und wenn wir nur den booleschen Wert prüfen, wird vielleicht ein Code-Benutzer später einfach eine Zeichenkette einfügen, weil er weiß, dass nicht leere Zeichenketten immer wahr sind. Das könnte ihm einen Cast ersparen.

Wenn die Argumente ungültige Werte haben, wird ValueError ausgelöst. Dies scheint in Ihrem Fall angemessener zu sein:

if recurse and not save:
    raise ValueError("If recurse is True, save should be True too")

Oder in diesem speziellen Fall, dass ein Wahr-Wert von recurse einen Wahr-Wert von save impliziert. Da ich dies als Wiederherstellung nach einem Fehler betrachten würde, sollten Sie sich vielleicht auch im Protokoll beschweren.

if recurse and not save:
    logging.warning("Bad arguments in import_to_orm() - if recurse is True, so should save be")
    save = True

4 Stimmen

Ich denke, das ist die genaueste Antwort. Es wird offensichtlich unterschätzt (bisher 7 Stimmen, einschließlich meiner).

16voto

Eli Courtwright Punkte 174547

Ich habe meistens nur die eingebauten ValueError in dieser Situation verwendet.

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