Kosten für Ausnahmebehandlungsroutinen in Python

97

In einer anderen Frage schlug die akzeptierte Antwort vor, eine (sehr billige) if-Anweisung im Python-Code durch einen try / exception-Block zu ersetzen, um die Leistung zu verbessern.

Abgesehen von Problemen mit dem Codierungsstil und der Annahme, dass die Ausnahme niemals ausgelöst wird, wie viel Unterschied macht es (in Bezug auf die Leistung), einen Ausnahmebehandler zu haben, anstatt keinen zu haben, im Vergleich zu einer if-Anweisung, die mit Null verglichen wird?

Thilo
quelle
6
Was haben Sie gelernt, als Sie es gemessen haben?
S.Lott
1
Verwandte Frage: stackoverflow.com/questions/1835756
tzot
Verwenden Sie try / außer wenn die Wahrscheinlichkeit einer Kontrolle mit Ausnahme eines Teils geringer ist und wenn / sonst wenn die Wahrscheinlichkeit größer ist.
shadow0359

Antworten:

112

Warum messen Sie es nicht mit dem timeitModul ? Auf diese Weise können Sie sehen, ob es für Ihre Anwendung relevant ist.

OK, also habe ich gerade Folgendes versucht:

import timeit

statements=["""\
try:
    b = 10/a
except ZeroDivisionError:
    pass""",
"""\
if a:
    b = 10/a""",
"b = 10/a"]

for a in (1,0):
    for s in statements:
        t = timeit.Timer(stmt=s, setup='a={}'.format(a))
        print("a = {}\n{}".format(a,s))
        print("%.2f usec/pass\n" % (1000000 * t.timeit(number=100000)/100000))

Ergebnis:

a = 1
try:
    b = 10/a
except ZeroDivisionError:
    pass
0.25 usec/pass

a = 1
if a:
    b = 10/a
0.29 usec/pass

a = 1
b = 10/a
0.22 usec/pass

a = 0
try:
    b = 10/a
except ZeroDivisionError:
    pass
0.57 usec/pass

a = 0
if a:
    b = 10/a
0.04 usec/pass

a = 0
b = 10/a
ZeroDivisionError: int division or modulo by zero

Wie erwartet ist es also etwas schneller, keinen Ausnahmebehandler zu haben (aber in die Luft zu jagen, wenn die Ausnahme auftritt) und try/exceptschneller als ein expliziter if, solange die Bedingung nicht erfüllt ist.

Aber es ist alles in der gleichen Größenordnung und es ist unwahrscheinlich, dass es so oder so eine Rolle spielt. Nur wenn die Bedingung tatsächlich erfüllt ist, ist die ifVersion deutlich schneller.

Tim Pietzcker
quelle
3
Interessant. Also try/exceptist schneller alsif a != 0
Thilo
10
Ahh, eine gute Wortwahl: "Es liegt alles in der gleichen Größenordnung" ... Ich vermute, dass viele Leute, die Ausnahmen vermeiden, damit rechnen, dass sie 10x so langsam sind.
Garrett Bluma
Das Ausführen Ihres Codes auf meinem Fedora mit Python 2.7.5 zeigt, dass die "if" -Version (0,08 usec / pass) schneller ist als die "try / Except" -Version (0,11 usec / pass), wenn a = 1.
Duleshi
@ Duleshi Interessant. Ich frage mich, ob es eine x86 / x64-Sache ist. Oder vielleicht andere Prozessorerweiterungen?
Basic
58

Diese Frage wird tatsächlich in den FAQ zu Design und Verlauf beantwortet :

Ein Try / Except-Block ist äußerst effizient, wenn keine Ausnahmen ausgelöst werden. Eine Ausnahme zu fangen ist teuer.

Michael
quelle
3
Ich habe mich nur gefragt, wie effizient "extrem effizient" ist. Anscheinend ist es schneller als sogar eine sehr einfache "Wenn" -Anweisung.
Thilo
Der von Ihnen veröffentlichte Auszug stammt aus den FAQ zu Design und Verlauf .
Nitsas
Vielleicht bedeutet "extrem effizient" so etwas wie das, was in Java gemacht wird ?
Ebk
18

Diese Frage ist irreführend. Wenn Sie davon ausgehen, dass die Ausnahme niemals ist ausgelöst wird, der beiden Codes optimal.

Wenn Sie davon ausgehen, dass die Ausnahme als Teil einer Fehlerbedingung ausgelöst wird, sind Sie bereits außerhalb des Bereichs, in dem Sie optimalen Code wünschen (und Sie behandeln ihn wahrscheinlich sowieso nicht auf einer genau abgestimmten Ebene).

Wenn Sie die Ausnahme als Teil des Standardkontrollflusses verwenden - dies ist die pythonische Methode "Bitte um Vergebung, nicht um Erlaubnis" -, wird die Ausnahme ausgelöst, und die Kosten hängen von der Art der Ausnahme und der Art des Falls ab und wie viel Prozent der Zeit, in der Sie die Ausnahme schätzen, passiert.


quelle