Text responses in python: Input() function and dialogue boxes

If this template helps then use it. If not then just delete and start from scratch.

**OS: macOS Catalina 10.15.4
**PsychoPy version: 2020.1.2
**Standard Standalone: YES

What are you trying to achieve?:
Use the input() function from python 3 to get and display words which people have to type.

What did you try to make it work?:
In a very simple routine in the builder with a Text and a Keyboard element, I have as well a Code component with the following code at the binging of the routine.

myText = input("Word: ")
print(myText)

In Spyder, if I run these lines, the first line runs and allows me to type some text until I hit “return”. Then the typed text is stored in the variable “myText” and becomes available to be used for any other purpose (e.g. printing its value as in the second line).

The whole idea is to capture the text being written by participants in the variable “myText” (set to refresh every frame) and use it to continuously update the value of the Text component. The Keyboard component is set to end the routine when “return” is hit.

What specifically went wrong when you tried that?:
However, this does not work as. I have tried different things but I keep getting the error below:

myText = input("Word: ")
EOFError: EOF when reading a line

I already know how to get keyboard responses through the Keyboard component, storing them and updating their value after every frame. Using input() over the usual Keyboard component code to do so has many potential advantages. In particular, I am struggling to be able to get Chinese characters as input from the keyboard and store the text in a variable. When using the input() function in Spyder it works perfectly, however, this cannot be done using the Keyboard component of Psychopy. It seems it was design to capture the moment in which a specific key is pressed, rather than to capture text input.
I wrote a comment in the following unsolved thread in which I explain in more detail how Chinese people usually type characters: [Typing Chinese during Experiment]

Any suggestions?

@miguel_santin, see this recent related post

Thank you for the link to the related post. The suggested approach for using input() is to embed the function in a Try structure with an Exception for the EOFError as in the code below. The whole idea is to create an exception for the EOFError so that a vale is returned by the function “process_input()” and the codes keeps being executed despite coming across such error.

def process_input():
    try:
        capturedText = input("Word: ")
    except EOFError:
        capturedText = "EMPTY FIELD"
        return capturedText
    return capturedText

myText = process_input()
print(myText)

However, this does not work either.

Even though a value in the variable capturedText is correctly returned by the function process_input(), then stored in the variable myText and later on passed on to the Text component to display such text onscreen, the only value that the variable captureText can take is “EMPTY FIELD” (de defined value in case of an EOFError. Furthermore, there is no time for typing any input: After executing the code at the beginning of the routine, Psychopy proceeds to execute any lines code that may be required to be executed at every frame during the routine. This does not allow the input() function to receive a response and pass it to myText. That is why the EOFError is occurring. The function is being forced to terminate before completing.

I need that the execution of the code in Psychopy waits until a response from input is entered so that it can then be passed to the required variable for using it.

Any ideas?

I was shocked when I noticed that Psychopy does not have a built in input-text component given how needed and frequent this is for all sort of tasks. Maybe it is a feature to really think about adding in the near future?

@miguel_santin, if your goal is to get keyboard input from the user during a task, there are several options.

@dvbridges, first of all thank you for taking some time from your busy schedule to read my posts and looking for some relevant links to help me out with the problem I have.

The Pavlovia demos work exactly as my experiment when I opened the thread here. We both use TextBox components to display text while it is typed and they work neatly when the matter is only about typing responses in English. However, both approaches (which are actually the same) fail to allow the entry of Chinese characters (which are a composition of two or more letters, and every composed string can refer to any of four or more different characters, which people need to disambiguate by choosing which one is the intended one). So the Pavlovia demos using TextBox components, despite being nice and clear, cannot take me forward.

I tried today the Dialogue Box approach. After spending several hours of trial and error and debugging a lot, I figured out how they work within Psychopy. Basically, whenever a Dialogue Box is displayed, the whole Psychopy code pauses running until some text is typed in its input box and the user click “Ok” or “Cancel”. When the box closes, the typed value is stored in the data attribute of the Dialogue box. This allows users to type in the input box any kind of special character (including Chinese characters) and this input value can be later on passed to another variable in the code. It is not an elegant, intuitive, and user friendly solution but… it works :ok_hand:t4:


For people who may be interested in the Dialogue Box solution:

I created a function at the beginning of the experiment to create a Dialogue Box when needed in the experiment. It has two arguments (text1 and text2) which are ued to store and return the input values typed by the user (in case something was typed).

def showTextBox(text1="", text2=""):
    textBox = gui.Dlg(title='Type your response here')
    textBox.addField('Label1: ', text1)
    textBox.addField('Label2: ', text2)
    textBox.show()
    if textBox.OK:
        text1 = textBox.data[0]
        text2 = textBox.data[1]
        return text1, text2
    else:
        return text1, text2

To use this function to make a Dialogue Box appear, and pause the execution of the Psychopy code until the box is closed, it only needs to be called at any moment during the execution of the code (either a the beginning, during or at the ending of a routine). I used the code below to call this function and assign its input values to different Text variables along the experiment.

stimuli1A, stimuli1B = showTextBox("default text 1A", "default text 1B")
stimuli2A, stimuli2B = showTextBox("default text 2A", "default text 2B")
stimuli3A, stimuli3B = showTextBox("default text 3A", "default text 3B")

It is a pitty that Psychopy does not offer a more elegant, intuitive and user friendly solution to type any kind of text, show it onscreen and store the input value. The use of the input() function seems like a very convenient and nice approach to cover this gap, however, differently from Dialogue Boxes, its use does not pause the execution of the Python code, which brings about an EOFError. Hopefully this could be addressed in the future. Many Psychopy users would be very thankful.

1 Like

Additionally, if you are interested in using Dialogue Boxes in an online experiment, go to the post below. I managed to make it work using JavaScript. I essentially needed to use Dialogue boxes to collect input data in Mandarin Chinese. Currently, Psychopy do not have a dedicated component for text input. As such, Dialogue Boxes are the only means for colecting complex text input such as Mandarin Chinese and Japanese.

Hello miguel_santin and @dvbridges, would it be possible to get a working script that uses the Dialogue Box approach for Chinese input?
I have tried constructing a simple script based on the code provided above and have failed to get anything running. Seeing as this is a repetitive issue with Psychopy and there are many users that would like to be done with this problem, the community would be greatly served by having a concrete example, i.e., a script, that works.

@karlneergaard in my experiments it works perfectly. During the last days I have been working on some adjustments to the procedure and the text box still works. It maybe that there is something wrong in your code. Please provide a more detailed description of the problem and errors you are comming across.

Btw, did you make sure to import the gui module from the psychopy package before using the code that I provided? If not, make sure to put the code below before the definition of the function that creates the dialogue boxes.

from psychopy import gui

Best,
Miguel