| Reference | Downloads | Github

3 ways to get keyboard input - which is best?

Looking through the docs I’m puzzled that there appear to be three ways to interact with the keyboard using any of the following

  1. psychopy.event
  2. psychopy.iohub
  3. psychopy.hardware

I’ve not noticed any comment on whether any particular approaches are preferred and what the pros/cons might be.

Can anyone shed some light and offer any advice on this apparent replication of functionality ?


1 Like

TL;DR it depends what you want to do, but most of the time event or hardware will do what you need.

If all you need is to get “was a key pressed, which one, and when”, then the event functions are probably your best bet. It’s sort of the “default” for PsychoPy. It checks whether a key has been pressed, and it gets a list of the keys and their timestamps.

When it comes to keyboards, hardware is basically the same as event, just newer and shinier, and it adds the ability to pull duration information (i.e., how long a key was held down, after it has been released). If you were using more than one keyboard, hardware.keyboard can handle that too.

By and large iohub would only be worth it if you were already using iohub for something else, like an eye-tracker, and I believe it’s better at letting you send events to other hardware, but having not done much of that myself I can’t swear to it. Iohub is also more useful if you find yourself using a non-standard keyboard in some way, or a non-standard input that you want to treat like a keyboard.

There’s also other things you can do if, for example, you want to check on each frame whether a given key is being held down. Iohub can handle this, but I find it easier to just access the Pyglet keyboard events directly in that case. See here: Tracking Key release


Jonathan is right, but I’d go further and advocate use of psychopy.hardware.keyboard over psychopy.event, and effectively regard the latter as deprecated (at least for keypress handling - it can still be used for dealing with mice).

Keyboard is as easy to use as the event module, but its performance is far better. It will perform similarly to ioHub, but be easier to use (partly because ioHub can do so many other things as well).

Of most relevance to most people is that the response time associated with a keypress is now the time the key was actually pressed, not the time you checked it. The latter is how the event module works, which is not obvious to people, and is why reaction times tend to have a 16 ms granularity in many scripts, if a call to event.getKeys() is made only once per screen refresh. Keyboard.getKeys() can be called on the same schedule (or even less frequently), and still give you the actual time of the keypress, because, a bit like ioHub, the checking is happening in a separate process from the main PsychoPy process.

The docs explain the differences here, and note that the Keyboard object effectively replaces the event module for keypress handling:

One limitation, though, is that there doesn’t seem to be a .waitKeys() function written for it yet (although a user can implement that themselves just be calling Keyboard.getKeys() in a loop).


Thanks both for the helpful explanations. Especially good to know that psychopy.event has effectively been deprecated for keyboard handling by psychopy.hardware.keyboard Also great to have highlighted that the frame-rate granularity of keyboard response times (which I knew about) has been overcome by the psychopy.hardware.keyboard implementation.

I agree with the other comments.

I do still find the iohub keyboard event .char field useful when you want to know the character that would be typed for a keyboard event, factoring in modifiers etc, and not just the key itself. The psychopy/demos/coder/iohub/ example displays the iohub .key and .char values for each iohub keyboard event it receives, as well as the value returned by psychopy.event.getKeys(), so you can see the differences.

PS: If you do try the demo, it has been reported that iohub may be broken again on macOS, so you might want to try using Windows or Linux instead. :wink: