Стоимость обработчиков исключений в Python

98

В другом вопросе в принятом ответе предлагалось заменить (очень дешевый) оператор if в коде Python на блок try / except для повышения производительности.

Если оставить в стороне проблемы со стилем кодирования, и если предположить, что исключение никогда не запускается, насколько сильно отличается (с точки зрения производительности) наличие обработчика исключений по сравнению с отсутствием его и условием сравнения с нулем?

Тило
источник
6
Что вы узнали, когда измерили его?
S.Lott
1
Связанный вопрос: stackoverflow.com/questions/1835756
tzot
Используйте try / except, если шансы на управление за исключением части меньше и if / else, если шансы больше.
shadow0359

Ответы:

114

Почему бы вам не измерить это с помощью timeitмодуля ? Таким образом вы сможете увидеть, подходит ли он для вашего приложения.

Хорошо, я только что попробовал следующее:

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

Результат:

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

Итак, как и ожидалось, отсутствие обработчика исключений немного быстрее (но взрывается вам в лицо, когда возникает исключение) и try/exceptбыстрее, чем явное, ifпока условие не выполняется.

Но все это в одном порядке и вряд ли будет иметь значение. Только если условие действительно выполняется, ifверсия будет значительно быстрее.

Тим Пицкер
источник
3
Интересный. Так try/exceptбыстрее, чемif a != 0
Тило,
10
Ах, хороший выбор слов: «все в одном порядке» ... Я подозреваю, что многие люди, избегающие исключений, делают это, ожидая, что они будут в 10 раз медленнее.
Garrett Bluma
Запуск вашего кода на моей Fedora с python 2.7.5 показывает, что версия «if» (0,08 мксек / проход) быстрее, чем версия «try / except» (0,11 мксек / проход), когда a = 1.
Дулеши
@duleshi Интересно. Интересно, это что за x86 / x64? Или, возможно, разные расширения процессора?
Basic,
59

Ответ на этот вопрос можно найти в FAQ по дизайну и истории :

Блок try / except чрезвычайно эффективен, если не возникают исключения. На самом деле перехват исключения стоит дорого.

Майкл
источник
3
Мне просто было интересно, насколько эффективно «чрезвычайно эффективно». Очевидно, это быстрее, чем даже очень простой оператор «если».
Тило
Опубликованный вами отрывок взят из FAQ по дизайну и истории .
nitsas
Может быть, «чрезвычайно эффективный» означает что-то вроде того, что сделано в Java ?
ebk
19

Этот вопрос вводит в заблуждение. Если вы предполагаете, что исключение никогда не запускается, ни один из них не является оптимальным кодом.

Если вы предполагаете, что исключение запускается как часть состояния ошибки, вы уже находитесь за пределами области, требующей оптимального кода (и, вероятно, вы все равно не обрабатываете его на таком мелкомасштабном уровне).

Если вы используете исключение как часть стандартного потока управления - а это метод Pythonic «просить прощения, а не разрешения» - то исключение будет инициировано, и его стоимость будет зависеть от типа исключения, типа if , и в какой процент времени, по вашему мнению, происходит исключение.


источник