prompt_toolkit not responding to Ctrl+D in Python try/except block

46 views Asked by At

I'm currently working on a Python 3.11.5 script on Linux Mint 21.2 that utilizes the prompt_toolkit library to create a simple command-line interface for updating information about a person. However, I've encountered an issue where the script does not respond to Ctrl+D as expected, but does respond to Ctrl+C.

from prompt_toolkit import prompt
from prompt_toolkit.key_binding import KeyBindings

def main():
    person = {
        'id': 1, 'name': "David", 'age': 24
    }

    kb = KeyBindings()
    user_input = None

    for column_name, column_value in person.items():
        prompt_text = f"Enter person's {column_name.replace('_', ' ').title()}: "
        try:
            user_input = prompt(prompt_text, default=str(column_value), key_bindings=kb).strip()

        except KeyboardInterrupt:
            print("Control-C pressed")

        except EOFError:
            print("Control-D pressed")

        person[column_name] = user_input if user_input else column_value

    print("Updated person:", person)

if __name__ == "__main__":
    main()

The app defines a main function that initializes a dictionary called person with some default values (id, name, and age). It then iterates through the dictionary's items, prompting the user to enter new values for each attribute. The prompts are displayed using the prompt_toolkit.prompt function, and the default values for each prompt are set based on the current values in the person dictionary.

The script handles interrupts caused by the user pressing Ctrl+C (KeyboardInterrupt) or Ctrl+D (EOFError) during input. If such interruptions occur, appropriate messages are printed.

After collecting the user's input for each attribute, the script updates the person dictionary with the new values. Finally, it prints the updated person information.

In summary, this app serves as a simple interactive command-line tool for updating information about a person, demonstrating the use of the prompt_toolkit library for user input in a console environment.

To reproduce the issue, press Ctrl+D while the script is running.

I've spent several hours reading the documentation at https://python-prompt-toolkit.readthedocs.io/en/master/ and searching the Internet for possible solutions, as well as trying out various code snippets, but to no avail.

When Ctrl+D is pressed in a terminal or console while using prompt_toolkit, it typically triggers an EOFError. The expected behavior is to catch the EOFError exception, in which case, the script will print "Control-D pressed" to the console, indicating that the user pressed Ctrl+D to signal the end of input.

However, when Ctrl+D is pressed, the interrupt signal is not caught by EOFError. Visually, nothing appears to happen at all in the terminal or console window, and the user can carry entering data without interruption.

Questions:

  1. Has anyone else encountered a similar problem with prompt_toolkit and Ctrl+D?
  2. Are there specific settings or configurations in prompt_toolkit that I might be overlooking?
1

There are 1 answers

0
Silverback On BEST ANSWER

Jonathan Slenders kindly answered my query on: https://github.com/prompt-toolkit/python-prompt-toolkit/issues/1837, which is as follows:


Control-d only works if there is no input present in the input field.

Given that a default value was given, the default first needs to be erased using backspaces, and then control-d works.

For different behavior, add this key binding:

@kb.add('c-d')
def quit(event):
    event.app.exit(exception=EOFError)

By adding the above key binding to my code, "except EOFError" is now able to catch Ctrl+D without having to backspace at all:

...
kb = KeyBindings()

@kb.add('c-d')
def quit(event):
    event.app.exit(exception=EOFError)

user_input = None
...