I was just looking at the Python FAQ because it was mentioned in another question. Having never really looked at it in detail before, I came across this question: “How fast are exceptions?”:
A try/except block is extremely efficient. Actually catching an exception is expensive. In versions of Python prior to 2.0 it was common to use this idiom:
try: value = mydict[key] except KeyError: mydict[key] = getvalue(key) value = mydict[key]
I was a little bit surprised about the “catching an exception is expensive” part. Is this referring only to those except
cases where you actually save the exception in a variable, or generally all except
s (including the one in the example above)?
I’ve always thought that using such idioms as shown would be very pythonic, especially as in Python “it is Easier to Ask Forgiveness than it is to get Permission”. Also many answers on SO generally follow this idea.
Is the performance for catching Exceptions really that bad? Should one rather follow LBYL (“Look before you leap”) in such cases?
(Note that I’m not directly talking about the example from the FAQ; there are many other examples where you just look out for an exception instead of checking the types before.)
Demerits of Python Exception Handling Like, programs that make use try-except blocks to handle exceptions will run slightly slower, and the size of your code will increase.
Now it is clearly seen that the exception handler ( try/except) is comparatively faster than the explicit if condition until it met with an exception. That means If any exception throws, the exception handler took more time than if version of the code.
try catch block does not slow down your program at all and is basically a standard for catching exceptions. Try Catch statements is basically your safe net when it comes to bugs in your code/program.
Catching exceptions is expensive, but exceptions should be exceptional (read, not happen very often). If exceptions are rare, try/catch
is faster than LBYL.
The following example times a dictionary key lookup using exceptions and LBYL when the key exists and when it doesn't exist:
import timeit
s = []
s.append('''\
try:
x = D['key']
except KeyError:
x = None
''')
s.append('''\
x = D['key'] if 'key' in D else None
''')
s.append('''\
try:
x = D['xxx']
except KeyError:
x = None
''')
s.append('''\
x = D['xxx'] if 'xxx' in D else None
''')
for i,c in enumerate(s,1):
t = timeit.Timer(c,"D={'key':'value'}")
print('Run',i,'=',min(t.repeat()))
Run 1 = 0.05600167960596991 # try/catch, key exists
Run 2 = 0.08530091918578364 # LBYL, key exists (slower)
Run 3 = 0.3486251291120652 # try/catch, key doesn't exist (MUCH slower)
Run 4 = 0.050621117060586585 # LBYL, key doesn't exist
When the usual case is no exception, try/catch
is "extremely efficient" when compared to LBYL.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With