I have a code with a one-liner while
and a try
-except
statement which behaves weirdly.
This prints 'a' on Ctrl+C:
try:
while True:
pass
except KeyboardInterrupt:
print("a")
and this too:
try:
i = 0
while True: pass
except KeyboardInterrupt:
print("a")
but this doesn't, and it throws a traceback:
try:
while True: pass
except KeyboardInterrupt:
print("a")
and neither does this code:
try:
while True: pass
i = 0
except KeyboardInterrupt:
print("a")
Addition some additional details.
In 3.11, the instruction JUMP_BACKWARD
was added and seems invloved with this issue see: Disassembler for Python bytecode
In 3.12 when the code in the first and the 3rd blocks are disassembled the results are:
Cannot be caught:
0 0 RESUME 0
2 2 NOP
3 >> 4 JUMP_BACKWARD 1 (to 4)
>> 6 PUSH_EXC_INFO
4 8 LOAD_NAME 0 (KeyboardInterrupt)
10 CHECK_EXC_MATCH
12 POP_JUMP_IF_FALSE 11 (to 36)
14 POP_TOP
5 16 PUSH_NULL
18 LOAD_NAME 1 (print)
20 LOAD_CONST 1 ('a')
22 CALL 1
30 POP_TOP
32 POP_EXCEPT
34 RETURN_CONST 2 (None)
4 >> 36 RERAISE 0
>> 38 COPY 3
40 POP_EXCEPT
42 RERAISE 1
ExceptionTable:
4 to 4 -> 6 [0]
6 to 30 -> 38 [1] lasti
36 to 36 -> 38 [1] lasti
None
Can be caught:
0 0 RESUME 0
2 2 NOP
3 4 NOP
4 >> 6 NOP
3 8 JUMP_BACKWARD 2 (to 6)
>> 10 PUSH_EXC_INFO
5 12 LOAD_NAME 0 (KeyboardInterrupt)
14 CHECK_EXC_MATCH
16 POP_JUMP_IF_FALSE 11 (to 40)
18 POP_TOP
6 20 PUSH_NULL
22 LOAD_NAME 1 (print)
24 LOAD_CONST 1 ('a')
26 CALL 1
34 POP_TOP
36 POP_EXCEPT
38 RETURN_CONST 2 (None)
5 >> 40 RERAISE 0
>> 42 COPY 3
44 POP_EXCEPT
46 RERAISE 1
ExceptionTable:
4 to 8 -> 10 [0]
10 to 34 -> 42 [1] lasti
40 to 40 -> 42 [1] lasti
None
The main differences that jump out are the two additional NOP
and the different targets for JUMP_BACKWARD
.
Note: the exception really cannot be caught as this will also throw the exception in 3.12
try:
try:
while True: pass
except KeyboardInterrupt:
print("a")
except Exception:
print("b")
KeyboardException
exception occurred during thewhile True: pass
statement. Just as if there were notry/except
– JanessaKeyboardInterrupt
– Rinarinaldi