You could try a Python binding for one of the cross-platform HID APIs. I did that on Linux a couple of months ago for one of these arcade joysticks and an old Gravis Gamepad Pro. It should work for any USB joystick, they are all HID devices.
The documentation was lacking for that Python HID binding so I read the underling C API which it called and also experiment with some of the Python calls to learn how it worked. Reading from one of those joysticks blocked until there was input and for the other reading always returned immediately. For the one which blocked I created a python thread which blocked on input and wrote to a thread-safe structure which the main Python thread checked. I think for the other joystick I just polled it on each pass through the main 60Hz drawing loop, the input is buffered so you don’t lose anything even if the button press duration could be less than 1/60th of a second or whatever is you animation loop period.
That was for an in-house project at Aeon Imaging and I left that code there so I don’t have anything to share here. It all worked perfectly in the end but was not especially quick and easy to write. Threading in Python is easy but still more work than not.
PyGame and Pyglet both support joysticks but their joystick stuff is integrated with the event systems for those APIs. That did not work for my application but might be fine for what you are doing and should be much easier code to than is that HID API binding. Also, PyGame was broken on my Ubuntu install, they seem to be having maintenance issues so Pyglet might be the better choice there.
It looks like the Psychopy distribution includes on of those HID bindings, which I just noticed now, Jon has a note about that here.