Continuous keypress log is logging the previous keypress if participants switch keys too fast

PsychoPy version 2022.2.5
Keyboard Backend Psychtoolbox
Standard Standalone? (y/n) yes
What are you trying to achieve?: Participants are always pressing one of four keys during a rating period. I’d like to log the key being pressed and the timestamp from an internal timer every 30 frames.

begin routine:

TrialData = []
thisframe = 0
status =['up', 'up', 'up', 'up']

each frame:

keys = mykb.getKeys(keysWatched, waitRelease = False, clear = False)
thisframe += 1

if len(keys):
    for i, key in enumerate(keysWatched):
        if keys[-1].name == key:
            if keys[-1].duration:
                status[i] = 'up'
            else:
                status[i] = 'down'

if thisframe == 30:
    if len(keys):
        for i, key in enumerate(keysWatched):
            if status[i] == 'down':
                TrialData.append([key, myClock.getTime()])

if thisframe == 30:
    thisframe = 0

What specifically went wrong when you tried that?:
When the participants switch keys slowly (e.g by using the same finger to rate each time so they have to lift it off of the previous key), this code works. But when participants press a different key too quickly (eg. even when told not to, they switch quickly using a different finger), psychopy doesnt detect that the old key has been lifted. This results in an output that logs two different keypresses at simultaneous timepoints until the key is changed again.

for example, here’s a section of the list output where 2 is being pressed but it’s still logging the old “3” press:

[3, 3228.122306900099], [2, 3228.6226221006364], [3, 3228.6226281002164], [2, 3229.12259640079], [3, 3229.1226011002436]

an example plot:

What did you try to make it work?:
(I’ve been able to replicate the type of pressing that’s causing the problem)

  1. A different keyboard - same issue
  2. setting the bufferSize of the keyboard to 1
  3. setting clear in getKeys to True
  4. setting waitRelease in getKeys to True
  5. using mykb.clearEvents() in the if statement when thisframe is set back to 0
  6. using mykb.clearEvents() in the beginning of each frame

I’m guessing that the issue is that the release of the previous key isn’t being recorded, so it continues to have a .duration property leading to it being logged in the list. I’m not sure how to fix this…