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.