I'm making use of the keyboard
package to capture key events in a python program. Take this simple script with the following:
import keyboard
while True:
try:
if keyboard.is_pressed('ESC'):
break
else:
pass
except:
break
When I run this script in terminal it behaves as expected until the program closes, at which point everything I typed is entered into the bash terminal as shell commands. This could be dangerous, as every line entered has the possibility of creating adverse system effects.
Any suggested workarounds for this? Pure python solutions preferred but script initialization parameters in bash are suitable.
You are using a global keyboard hook to read input for a single terminal. This is bad design because it spies on events the user may have meant for other programs, it stops your program from working like a normal terminal program (e.g. it won't run over ssh
), and since you don't touch your own input queue you will see duplicated input (as you've discovered).
The better solution is to set the tty to raw mode, and keep reading single keypresses until you want to exit
#!/usr/bin/env python3
import termios, tty, sys
# Save terminal settings
old = termios.tcgetattr(0)
# Disable buffering
tty.setcbreak(0)
# Read until Esc
while sys.stdin.read(1) != "\x1B":
pass
# Set the terminal settings back
termios.tcsetattr(0, termios.TCSANOW, old)
If you prefer your design, you can flush the input queue before you exit:
import termios
termios.tcflush(0, termios.TCIFLUSH)