I have writing the following code to get key pressed by the user:
class Key:
def __init__(self) -> None:
pass
# Define the function that will be called when a key is pressed.
def on_press(self, key: KeyType) -> None:
pass
# Define the function that will be called when a key is released.
def on_release(self, key: KeyType, queue: Queue, listener: Listener) -> None:
try:
# Put the character key in the queue.
queue.put(key.char)
# Stop the listener
listener.stop()
except AttributeError:
# Put non-character keys in the queue.
queue.put(key.name)
# Stop the listener
listener.stop()
def get_key(self, prompt_string: str) -> str:
'''
Prompts the user for a key.
Args:
prompt_string (str): A string representing the prompt to display to the user
Returns:
key (str): A key which the user pressed
Examples:
To prompt the user for a key and print the key that was pressed, use:
>>> key = get_key("Press a key: ")
>>> print("You pressed:", key)
'''
# Create a new queue object to hold the key value.
key_queue = Queue()
# Start a keyboard listener with the on_press and on_release functions.
# Use a lambda function to pass the queue object to the on_release function.
with Listener(on_press=self.on_press, on_release=lambda key: self.on_release(key, queue=key_queue, listener=listener)) as listener:
# Print the prompt string to the console.
# Use flush=True to ensure that the message is printed immediately.
# Use end='' to make sure that the next print statement is on the same line.
print(prompt_string, end='', flush=True)
# Initialize the key value to None.
key = None
# Keep looping until a key value has been retrieved from the queue.
while key is None:
key = key_queue.get()
# Return the key value to the calling function.
return key
I call the above code in a separate file after which I ask the user for a input using the input()
function.
# Get key to be autoclicked from user by calling get_key function with a prompt message.
button = key.get_key(f"{INPUT_COLOR}Key to be autoclicked (press any key): {RESET}")
# Print the button that the user has pressed.
print(USER_INPUT_COLOR + button + RESET)
# Get delay between key presses in seconds from user by calling get_input function with a prompt message.
delay = float(input(f"{INPUT_COLOR}Delay between key presses (in seconds): {USER_INPUT_COLOR}"))
print(f"{RESET}", end="")
But when the above code is executed I can press a button to enter a key for the button input but for the delay input when try to enter a float value like '0.1', it doesn't show anything that I am typing. Furthermore when I press enter after typing '0.1' it gives this error: ValueError: could not convert string to float: 'mqe0.1'
or other times the error changes to this: ValueError: could not convert string to float: 'kqer0.1'
.
After this the program naturally exists but I find that the terminal seems to be broken because whatever I type seems to not be displayed but it is there because when I enter the terminal responds to whatever I typed but doesn't show it.
Some extra info:
f'{INPUT_COLOR}'
and f'{RESET}
are just constant values for ansi escape codes that I have defined in another file and they are not causing the issue.What I have tried:
I tried adding a listener.stop()
to the listener
for getting key presses but that doesn't change anything
Is this a problem with Pynput on linux or a problem with the code I have written? Any help would be appreciated!
So this problem of the bash terminal breaking, where it doesn't respond to what you are typing can be fixed by executing the command reset
in the terminal.
So for the app I just needed to add a os.system("reset")
line after you are done using pynput to listen for key presses.
So the example code becomes:
# Get key to be autoclicked from user by calling get_key function with a prompt message.
button = key.get_key(f"{INPUT_COLOR}Key to be autoclicked (press any key): {RESET}")
# Print the button that the user has pressed.
print(USER_INPUT_COLOR + button + RESET)
# Reset the terminal
os.system("reset")
# Get delay between key presses in seconds from user by calling get_input function with a prompt message.
delay = float(input(f"{INPUT_COLOR}Delay between key presses (in seconds): {USER_INPUT_COLOR}"))
print(f"{RESET}", end="")
This does erase the previous output from the terminal, but you can code a workaround for that.