Costo de manejadores de excepciones en Python

En otra pregunta , la respuesta aceptada sugirió reemplazar una statement if (muy barata) en el código Python con un bloque try / except para mejorar el rendimiento.

Dejando a un lado los problemas de estilo de encoding, y suponiendo que la excepción nunca se active, ¿cuánta diferencia hace (en cuanto al rendimiento) tener un controlador de excepciones, en lugar de no tener uno, en lugar de tener una instrucción if de comparación a cero?

¿Por qué no lo mides usando el módulo timeit ? De esa manera puedes ver si es relevante para tu aplicación.

OK, así que he intentado lo siguiente:

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

Resultado:

 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 

Entonces, como era de esperar, no tener ningún controlador de excepciones es un poco más rápido (pero explota en su cara cuando ocurre la excepción), e try/except es más rápido que un explícito if la condición no se cumple.

Pero todo está en el mismo orden de magnitud y es poco probable que importe en ambos sentidos. Solo si la condición se cumple realmente, entonces la versión if es significativamente más rápida.

Esta pregunta se responde realmente en las preguntas frecuentes de diseño e historia :

Un bloque try / except es extremadamente eficiente si no se producen excepciones. En realidad atrapar una excepción es costoso.

Esta pregunta es engañosa. Si asume que la excepción nunca se activa, ninguno de los dos es un código óptimo.

Si asume que la excepción se desencadena como parte de una condición de error, ya está fuera del ámbito de desear un código óptimo (y probablemente no lo esté manejando en un nivel detallado como ese).

Si está utilizando la excepción como parte del flujo de control estándar, que es la forma Pythonic de “pedir perdón, no permiso”, la excepción se activará y el costo dependerá del tipo de excepción, del tipo de y qué porcentaje de tiempo estima que ocurre la excepción.