Рецепт ActiveState, похоже, содержит небольшую ошибку для систем «posix», которая предотвращает прерывание Ctrl-C
(я использую Mac). Если я поместил следующий код в свой скрипт:
while(True):
print(getch())
Я никогда не смогу закончить скрипт с помощью Ctrl-C
, и мне нужно убить мой терминал, чтобы уйти.
Я полагаю, что причиной является следующая строка, и она слишком жестока:
tty.setraw(sys.stdin.fileno())
Из-за этого пакет tty
на самом деле не нужен, termios
достаточно для его обработки.
Ниже приведен улучшенный код, который работает для меня (Ctrl-C
будет прерывать), с дополнительной функцией getche
, которая эхо-символа при вводе:
if sys.platform == 'win32':
import msvcrt
getch = msvcrt.getch
getche = msvcrt.getche
else:
import sys
import termios
def __gen_ch_getter(echo):
def __fun():
fd = sys.stdin.fileno()
oldattr = termios.tcgetattr(fd)
newattr = oldattr[:]
try:
if echo:
# disable ctrl character printing, otherwise, backspace will be printed as "^?"
lflag = ~(termios.ICANON | termios.ECHOCTL)
else:
lflag = ~(termios.ICANON | termios.ECHO)
newattr[3] &= lflag
termios.tcsetattr(fd, termios.TCSADRAIN, newattr)
ch = sys.stdin.read(1)
if echo and ord(ch) == 127: # backspace
# emulate backspace erasing
# https://stackoverflow.com/a/47962872/404271
sys.stdout.write('\b \b')
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, oldattr)
return ch
return __fun
getch = __gen_ch_getter(False)
getche = __gen_ch_getter(True)
Ссылки: