Is Python unpacking atomic w.r.t. interrupts?

Question:

Given the following example

try:
    a, b = 0, 0
    for _ in range(100):
        a, b = (a+1, b+1)
except KeyboardInterrupt:
    assert a == b

could an AssertionError be thrown? If so, is there a way to prevent it, i.e. to ensure that either both of a and b or none is updated on every iteration?


Possibly related to Is Python unpacking thread safe?

Within, the following example and corresponding opcode are given:

>>> def t(self): a,b=20,20
... 
>>> dis.dis(t)
  1           0 LOAD_CONST               2 ((20, 20))
              3 UNPACK_SEQUENCE          2
              6 STORE_FAST               1 (a)
              9 STORE_FAST               2 (b)
             12 LOAD_CONST               0 (None)
             15 RETURN_VALUE        

Since there are two separate instructions for storing a and b, I would expect that no guarantees can be given whether both or none of the two instructions is executed prior to a KeyboardInterrupt.

Asked By: Boyan Hristov

||

Answers:

Your intuition is correct: while Python will handle the interrupt internally and re-expose it separately (so interrupts are not quite as fraught as they are in C), as noted in e.g. PEP 343:

Even if you write bug-free code, a KeyboardInterrupt exception can still cause it to exit between any two virtual machine opcodes.

Answered By: Masklinn