Computers are frustrating, largely because they only do exactly what we tell them to
i.e. assuming your screen has a refresh rate of 60 Hz, your script above should only run for two refresh cycles (approximately 33 ms) before quitting.
The primary issue here is that sounds play asynchronously – the rest of your code continues while the sound plays in the background. So this check will almost certainly not evaluate to
if mySound_single.status == FINISHED:
i.e. the sound is still playing when this check is made, so the text won’t be shown. The next sound then starts playing, and then the experiment quits almost instantly afterwards. You probably won’t even hear the second sound start, as the
quit() occurs immediately after the
The wider issue here is that you should probably be using Builder to create the bones of your experiment. It would take about two minutes in Builder to create this section of your task, and everything would run properly (plus you would get all of the data collection and saving for free, and so on).
You clearly know how to program in Python, but the limitation here is knowing the detailed ins and outs of the PsychoPy API (e.g. you also mix references to the
event module and the
Keyboard object in quick succession, which can also cause unexpected results). Let Builder take care of all of that, and use your Python expertise only as required (by inserting small code snippets via code components when required).
This isn’t beginner-level advice: we would advise even the most experienced Python (and PsychoPy) developers to use this hybrid approach. It’s the best way of using your time and expertise, while letting Builder take care of all the tedious stuff, while ensuring that the code you are using is best-practice in terms of timing and so on.
e.g. I do still use some hand-crafted PsychoPy scripts from a decade ago. But for any new work, I start with Builder and just insert additional code snippets via code components as required. In my case, my custom code is largely for implementing experimental design considerations that Builder can’t provide for, but I let it handle most of the stimulus display and response collection stuff.
But how should you proceed if you want to continue with your own hand-crafted script? One way would be to look at how Builder scripts work. They tend to operate on a loop structure, with one iteration per screen refresh (i.e. each iteration ends with a
win.flip()). With that approach, you would be actively checking on each screen refresh whether the sound has finished playing (or the escape key has been pressed, and so on) and proceeding to the next step only when that has occurred. Having active monitoring loops like that avoids the code immediately running through to completion. e.g:
while mySound_single.status != FINISHED:
# should probably check for 'escape' here
# now will happen, but only after the sound has finished:
win.flip() in a loop like this seems arbitrary (i.e. what does screen drawing have to do with sound duration?), but has distinct advantages. Most particularly, it limits the rate of the loop to only once per screen refresh. Without it, the loop might iterate at millions of times per second. That would hog all the resources of your computer, and soon cause timing issues (i.e. the OS and other apps need time to “breathe” as well, and would soon start wrestling with your script for access to the CPU). Putting a pause in each loop iteration allows your script to be a good citizen, effectively sharing access to the CPU for a few milliseconds on each cycle, meaning that it won’t eventually get strangled by competing processes.