PyCharm not hitting Quick and Dirty breakpoint on "pass"

Viewed 409

I want to add a quick & dirty breakpoint, e.g when I am interested in stopping in the middle of iterating a long list.

for item in list:
    if item == 'curry':
        pass

I put a breakpoint on pass, and it is not hit(!).

If I add a following (empty) print

for item in list:
    if item = 'curry':
        pass
        print('')

and breakpoint both pass and print, only print is hit.

Any idea why? Windows 7, (portable) Python 3.7


[Update] as per the comment form @Adam.Er8 I tried inserting and breakpointing the ellipsis literal, ... but that was not hit, although the following print('') was.


[Updtae++] Hmm, it does hit a breakpoint on the pass in

for key, value in dictionary.items(): 
    pass
2 Answers

The pass doesn't actually make it into the bytecode. The code is exactly the same as if it wasn't there. You can see this using the dis module. (examples using 3.7 on linux).

>>> import dis
>>> dis.dis(dis.dis('for i in a:\n\tprint("i")')                                                                                               
  1           0 SETUP_LOOP              20 (to 22)
              2 LOAD_NAME                0 (a)
              4 GET_ITER
        >>    6 FOR_ITER                12 (to 20)
              8 STORE_NAME               1 (i)

  2          10 LOAD_NAME                2 (print)
             12 LOAD_CONST               0 ('i')
             14 CALL_FUNCTION            1
             16 POP_TOP
             18 JUMP_ABSOLUTE            6
        >>   20 POP_BLOCK
        >>   22 LOAD_CONST               1 (None)
             24 RETURN_VALUE
>>> dis.dis('for i in a:\n\tpass\n\tprint("i")')                                                                                       
  1           0 SETUP_LOOP              20 (to 22)
              2 LOAD_NAME                0 (a)
              4 GET_ITER
        >>    6 FOR_ITER                12 (to 20)
              8 STORE_NAME               1 (i)

  3          10 LOAD_NAME                2 (print)
             12 LOAD_CONST               0 ('i')
             14 CALL_FUNCTION            1
             16 POP_TOP
             18 JUMP_ABSOLUTE            6
        >>   20 POP_BLOCK
        >>   22 LOAD_CONST               1 (None)
             24 RETURN_VALUE

What the bytecode is doing isn't as relevant as the fact both blocks are identical. the pass is just ignored so there is nothing for the debugger to break on.

try replacing pass with ...:

for item in list:
    if item = 'curry':
        ...

you should be able to break-point there

this is called the ellipsis literal, unlike pass it is actually "executed" (well, sort of), and this is why you can break on it, like you would on any other statement, but it has 0 side effects and reads like "nothing" (before discovering this trick I'd just write _ = 0)

EDIT:

you can just set a conditional breakpoint.

In PyCharm this is done by right-clicking the bp and writing the condition: enter image description here

Related