0

I'm using and try/except statement in python inside a very long loop. If the exception is raised, it should do nothing.

try :
  *Some Code*
except :
  pass

If i use this first proposition, the total time of calculation for the loop is about 10 minutes.

try :
  *Some Code*
except :
  None

If i use this second propositon, the total time of calculation for the loop is about 2 minutes.

Why is it so different, and why is the second one faster as, logically for me, pass is a better solution than None ?

The exact code is :

try:
 indexes = peakutils.peak.interpolate(self.list_height, input_1, ind=indexes, width=self.gauss_width)
except:
 None / Pass

I made several tests with both propisitons and it's always the same.

How time is calculated :

start = default_timer()
im.get_events() #The loop where the try/except statement appears
finish = default_timer()
print('ELAPSED TIME : %s'%(finish - start))
Dedi
  • 35
  • 7

1 Answers1

3

Given two functions:

def func_none():
  return None

def func_pass():
  pass

They are doing exactly the same thing, the proof using dis:

>>> import dis
>>> dis.dis(func_none)
# 0 LOAD_CONST               0 (None)
# 3 RETURN_VALUE

>>> dis.dis(func_pass)
# 0 LOAD_CONST               0 (None)
# 3 RETURN_VALUE

Indeed, here is the definition of pass:

pass is a null operation — when it is executed, nothing happens. It is useful as a placeholder when a statement is required syntactically, but no code needs to be executed, for example:

Conclusion: pass statement is as fast as Nonein theory.

Edit: why it may be a slower time using None instead of return None (like in OP example).

Given two functions:

def func_none():
  try:
    1/0
  except:
    None

def func_pass():
  try:
    1/0
  except:
    pass

The difference using dis:

>>> import dis
>>> dis.dis(func_none)
# Skip to expect part

  18 LOAD_CONST               0 (None)
  21 POP_TOP             
  22 JUMP_FORWARD             1 (to 26)
  25 END_FINALLY         
  26 LOAD_CONST               0 (None)
  29 RETURN_VALUE  

dis.dis(func_pass)

# Skip to expect part

  18 JUMP_FORWARD             1 (to 22)
  21 END_FINALLY         
  22 LOAD_CONST               0 (None)
  25 RETURN_VALUE 

So it is clear that using None instead of pass will add two extra operation LOAD_CONST and POP_TOP. It shouldnt add 8 minutes though, so I'm sure this isn't the real reason.

Kruupös
  • 5,097
  • 3
  • 27
  • 43
  • 2
    This isn't exactly the same thing as the OP's code. A function implicitly returns `None` if there is no return statement, and `pass` does not compile to any code, which is why the two functions have the same disassembly on CPython. Adding `None` as a separate statement will add some code to load the constant, though, so it is actually slower than `pass`. – Sven Marnach Jul 05 '17 at 09:50
  • Thanks for the aswer. Even if it does not explain the reason, i am assured that it _should_ be identical. – Dedi Jul 05 '17 at 09:50
  • 2
    You could simply have changed the code of the `func_none()` to just `None` instead of `return None`, and you would have seen the same difference. This is not specific to try/except; it'st just how expression statements are compiled in CPython. – Sven Marnach Jul 05 '17 at 09:56
  • @Dedi, you are right, I edited my answer to add extra informations. It still does not explain the issue though. – Kruupös Jul 05 '17 at 09:57
  • @SvenMarnach, thanks for the comment, you are totally right, I edited the question to try to catch the difference in the second part. Do you think it is somewhat useful? – Kruupös Jul 05 '17 at 09:59
  • @Max Chrétien, thanks for this. As you can guess, it is a purely theorical question and does not really change the final code. – Dedi Jul 05 '17 at 09:59
  • 1
    @Dedi, yes I understand. this is a total legitimate question and I'm sorry I can't explain the reason of such a big gap between your 2 pieces of code. – Kruupös Jul 05 '17 at 10:03