Python кросс-платформенное прослушивание нажатий клавиш?
Мне нужно прослушивать определенные нажатия клавиш в терминальной программе python без приостановки выполнения с помощью raw_input
. Я видел, как люди используют несколько окон, способных прослушивать нажатия клавиш, и я видел, как люди используют большие модули, такие как tkinter и pygame, которых я хочу избежать.
Есть ли там легкий модуль, который делает эту кросс-платформу (по крайней мере, ubuntu, windows, mac)? или есть способ использовать только систему событий из tkinter, pygame и т.д.??
Если нет, как я должен подходить к этому решению? Моя первая мысль - перенаправить stdin на другой процесс и продолжать проверять, содержит ли он один из моих ключей событий.
изменить
Спасибо @unutbu за то, что нашли время, чтобы отметить этот вопрос, которому 3 года, и успешно ответили как дубликат другого вопроса, ответы которого не применяются к этому вопросу, потому что я специально спросил о неблокирующем решении.
Ответы
Ответ 1
Я не знаю ни одного кросс-платформенного модульного модуля, который прослушивает нажатия клавиш. Но вот предложение, если вы хотите реализовать что-то простое:
Проверьте этот вопрос на получение одного нажатия клавиши одновременно в FAQ Python. Вы можете немного поэкспериментировать с блокировкой чтения из sys.stdin
и threading
. Но это может работать только на Unix. В Windows вы можете использовать msvcrt.kbhit
.
Объединив рецепт keypress из часто задаваемых вопросов Python и модуля msvcrt
, результирующая функция kbhit
будет выглядеть следующим образом:
try:
from msvcrt import kbhit
except ImportError:
import termios, fcntl, sys, os
def kbhit():
fd = sys.stdin.fileno()
oldterm = termios.tcgetattr(fd)
newattr = termios.tcgetattr(fd)
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSANOW, newattr)
oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)
try:
while True:
try:
c = sys.stdin.read(1)
return True
except IOError:
return False
finally:
termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
Ответ 2
Короткий ответ: нет
Ключи к системе зависят от системы. Они управляются прерываниями. Это одна из основных вещей, встроенных в большинство современных ОС. Они имеют разные философии, которые не могут быть унифицированы общим способом, не теряя функциональности.
вы можете попробовать,
termios= unix, файл-дескриптор в стиле posix
curses= обработка дескриптора порталов (что представляет собой специфическую неконфиденциальную консольную версию)
Python обертывает определенные классы ввода, которые могут поступать с клавиатуры: например, sys.stdin для консоли inupt.
Но попытка получить универсальный ввод с клавиатуры - это очень общая проблема, которая по своей сути зависит от платформы.
Ответ 3
Здесь вы можете сделать это в Windows:
"""
Display series of numbers in infinite loop
Listen to key "s" to stop
Only works on Windows because listening to keys
is platform dependent
"""
# msvcrt is a windows specific native module
import msvcrt
import time
# asks whether a key has been acquired
def kbfunc():
#this is boolean for whether the keyboard has bene hit
x = msvcrt.kbhit()
if x:
#getch acquires the character encoded in binary ASCII
ret = msvcrt.getch()
else:
ret = False
return ret
#begin the counter
number = 1
#infinite loop
while True:
#acquire the keyboard hit if exists
x = kbfunc()
#if we got a keyboard hit
if x != False and x.decode() == 's':
#we got the key!
#because x is a binary, we need to decode to string
#use the decode() which is part of the binary object
#by default, decodes via utf8
#concatenation auto adds a space in between
print ("STOPPING, KEY:", x.decode())
#break loop
break
else:
#prints the number
print (number)
#increment, there no ++ in python
number += 1
#wait half a second
time.sleep(0.5)