0

When I try to call this function in my program, it will call the error (in the title) if I take to long to run the program. It seems like over 5 minutes spent on the program will cause it to crash.

Windows 8 Python 2.7 Psychopy 1.82.02

 def WaitForKeyInput():
    timer= core.CountdownTimer(5)
    trialClock.reset()
    text='...'
    #until return pressed, listen for letter keys & add to text string
    while event.getKeys(keyList=['return'])==[]:
        letterlist=event.getKeys(keyList=['0', '1', '2', '3', '4',  '5' , '6', '7', '8', '9','backspace','q'])
        color = 'black'
        if timer.getTime() >= 3:
            color = 'green'
        elif timer.getTime() >=0:
            color = 'yellow'

        elif timer.getTime() <0:
            color = 'red'
        feedback = visual.Rect(mywin, width= 200,height = 200, pos = (0,-100), lineWidth=5.0, lineColor = color)
           betAsk.draw()
           feedback.draw()
          response = visual.TextStim(mywin, height=36,text=text,color="white",pos=(0,-100))
        if text != '...':
            response.draw()
        mywin.flip()
        for l in letterlist:
             if l == 'q':
                 core.quit()
            #if key isn't backspace, add key pressed to the string
            if l !='backspace':
                if text =="...":
                    text=l
                    pressedkeys=l
                else:
                   text+=l
                   pressedkeys+=(";" + l)
                #otherwise, take the last letter off the string
                elif len(text)>0:
                    text=text[:-1]
                    pressedkeys+=(";backspace")
        event.clearEvents()
too honest for this site
  • 12,050
  • 4
  • 30
  • 52

1 Answers1

3

You should check out some of the PsychoPy demos to get more of a feel for how to use its classes. The general scheme is that where possible you should just create an object (e.g. feedback = visual.Rect(...)) just once. Then subsequently, just update its properties as required.

For example, in this case, on every iteration through the loop, you are needlessly recreating feedback. Instead, instantiate it just once, before the loop starts, and then simply call feedback.lineColor = colour to update just that property, followed by feedback.draw().

Why? At least two reasons:

  • Object creation generally takes a not-insubstantial time compared to just updating properties of an already existing object. In code like this, which is running on every screen refresh, such object creation can actually end up taking more than one screen refresh, and hence destroy your timing.

  • There is a memory leak in the underlying pyglet library that PsychoPy uses for text display. This is very probably what is creating your memory exception, due to you creating the response text stimulus thousands of times over.

So a solution would be to restructure your code to avoid multiple object creation, as a general principle, but also to avoid this annoying text memory leak over which PsychoPy has no real control.

You should also avoid having event.getKeys() in your while condition. It is immediately followed by another call to event.getKeys(). This will clear the queue of keypresses again, making it possible that you will often miss keypresses that would have been detected if you only checked once on every loop. Also, event.clearEvents() is likely unnecessary.

Michael MacAskill
  • 2,411
  • 1
  • 16
  • 28