Вартість оброблювачів винятків у Python


97

В іншому запитанні прийнята відповідь запропонувала замінити (дуже дешевий), якщо заява в коді Python на блок "try" ("виключати") для підвищення продуктивності

Стиль кодування відкладає сторону, і припускаючи, що виняток ніколи не спрацьовує, наскільки різницею (для продуктивності) є обробник винятків, а не його, порівняно з твердженням зі співвідношенням до нуля if-statement?


6
Коли ви її вимірювали, що ви дізналися?
S.Lott

1
Пов'язаний питання: stackoverflow.com/questions/1835756
tzot

Використовуйте спробу / за винятком випадків, коли шанси на контроль, крім частини, менші, а якщо / ще, якщо шанси більше.
shadow0359

Відповіді:


112

Чому ви не вимірюєте його за допомогою 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 показує, що версія "якщо" (0,08 usec / pass) швидша, ніж "спробувати / за винятком" (0,11 usec / pass), коли a = 1.
дулеші

@duleshi Цікаво. Цікаво, чи це річ x86 / x64? Чи, можливо, різні розширення процесора?
Основні

58

На це запитання відповіли насправді в FAQ щодо дизайну та історії :

Блок спробувати / винятком є ​​надзвичайно ефективним, якщо жодних винятків не виникає. Насправді зловити виняток дорого.


3
Мені було просто цікаво, наскільки ефективний "надзвичайно ефективний". Мабуть, це швидше, ніж навіть дуже просте твердження "якщо".
Тіло

Уривок, який ви опублікували, виходить із FAQ та питань дизайну та історії .
nitsas

Можливо, "надзвичайно ефективно" означає щось на кшталт того, що робиться на Java ?
ebk

18

Це питання вводить в оману. Якщо ви припускаєте, що виняток ніколи не спрацьовує, жоден з них не є оптимальним кодом.

Якщо ви припускаєте, що виняток спрацьовує як частина помилки, ви вже знаходитесь поза сферою бажання оптимального коду (і ви, ймовірно, не обробляєте його на тонкозернистому рівні, як це все одно).

Якщо ви використовуєте виняток як частину стандартного потоку управління - а це пітонічний спосіб "попросити пробачення, а не дозволу" - виняток буде ініційований, а вартість залежить від виду винятку, виду, якщо , і який відсоток часу, за яким ви оцінюєте, відбувається виняток.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.