Costo dei gestori di eccezioni in Python


97

In un'altra domanda , la risposta accettata suggeriva di sostituire un'istruzione if (molto economica) nel codice Python con un blocco try / tranne per migliorare le prestazioni.

Problemi di stile di codifica a parte e supponendo che l'eccezione non venga mai attivata, quanta differenza fa (dal punto di vista delle prestazioni) avere un gestore di eccezioni, rispetto a non averne uno, rispetto a un'istruzione if di confronto con zero?


6
Quando l'hai misurato, cosa hai imparato?
S.Lott


Usa try / tranne se le possibilità di controllo che va a tranne parte è inferiore e if / else se le possibilità sono maggiori.
shadow0359

Risposte:


112

Perché non lo misuri usando il timeitmodulo ? In questo modo puoi vedere se è rilevante per la tua applicazione.

OK, quindi ho appena provato quanto segue:

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))

Risultato:

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

Quindi, come previsto, non avere alcun gestore di eccezioni è leggermente più veloce (ma ti esplode in faccia quando si verifica l'eccezione) ed try/exceptè più veloce di un esplicitoif fintanto che la condizione non è soddisfatta.

Ma è tutto nello stesso ordine di grandezza ed è improbabile che abbia importanza in entrambi i casi. Solo se la condizione viene effettivamente soddisfatta, la ifversione è notevolmente più veloce.


3
Interessante. Quindi try/exceptè più veloce diif a != 0
Thilo

10
Ahh, un'ottima scelta di parole: "è tutto nello stesso ordine di grandezza" ... Sospetto che molte persone che evitano le eccezioni lo facciano aspettandosi che siano 10 volte più lente.
Garrett Bluma

L'esecuzione del codice sulla mia Fedora con python 2.7.5 mostra che la versione "if" (0.08 usec / pass) è più veloce di quella "try / tranne" (0.11 usec / pass) quando a = 1.
duleshi

@duleshi Interessante. Mi chiedo se sia una cosa x86 / x64? O forse estensioni del processore diverse?
Basic

58

Questa domanda trova effettivamente risposta nelle domande frequenti su Design e storia :

Un blocco try / tranne è estremamente efficiente se non vengono sollevate eccezioni. In realtà, catturare un'eccezione è costoso.


3
Mi stavo solo chiedendo quanto sia efficiente "estremamente efficiente". Apparentemente è più veloce anche di una semplice affermazione "if".
Thilo

L'estratto che hai pubblicato è tratto dalle domande frequenti su Design e storia .
nitsas

Forse "estremamente efficiente" significa qualcosa di simile a ciò che viene fatto in Java ?
ebk

18

Questa domanda è fuorviante. Se si presume che l'eccezione non venga mai attivata, nessuno dei due è codice ottimale.

Se si presume che l'eccezione venga attivata come parte di una condizione di errore, si è già fuori dal regno del desiderio di codice ottimale (e probabilmente non lo si sta gestendo a un livello così dettagliato comunque).

Se stai usando l'eccezione come parte del flusso di controllo standard - che è il modo pitonico "chiedi perdono, non permesso" - allora l'eccezione verrà attivata e il costo dipende dal tipo di eccezione, dal tipo di se e quale percentuale di tempo si stima si verifichi l'eccezione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.