Кросс-платформенный Python прослушивает нажатия клавиш? [дубликат]
На этот вопрос уже есть ответ здесь:
- Python считывает один символ от пользователя 20 ответов
Мне нужно прослушать определенные нажатия клавиш в терминальной программе python, не останавливая выполнение с помощью raw_input
. Я видел, как люди используют несколько специфичных для windows способов прослушивания нажатий клавиш, и я видел, как люди используют большие модули, такие как tkinter и pygame, которой я хочу избежать.
Есть ли легкий модуль, который делает эту кросс-платформу (по крайней мере ubuntu, windows, mac)? или есть способ использовать только систему событий от tkinter, pygame и т. д...?
Если нет, то как я должен подойти к решению этой проблемы? Моя первая мысль-перенаправить stdin на другой процесс и продолжать проверять, содержит ли он один из моих ключей событий.
Править
Спасибо @unutbu за то, что нашли время отметить этот вопрос, что является 3-летним и успешно ответил как дубликат другого вопроса, ответы которого не относятся к этому вопросу, потому что я специально спросил о неблокирующем решении.
3 ответа:
Я не знаю ни одного кросс-платформенного легкого модуля, который слушает нажатия клавиш. Но вот предложение на случай, если вы хотите реализовать что-то простое:
Проверьте этот вопрос наполучение одного нажатия клавиши одновременно в Python FAQ. Вы можете немного поэкспериментировать с блокировкой чтения из
sys.stdin
иthreading
. Но это может работать только на Unix. В Windows вы можете использоватьmsvcrt.kbhit
.Комбинируя рецепт нажатия клавиш из Python FAQ и модуль
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)
Короткий ответ: нет Нажатия клавиш зависят от системы. Они управляются прерываниями. Они одна из основных вещей, встроенных в большинство современных ОС. У них разные философии, которые не могут быть объединены общим способом без потери функциональности.
Вы можете попробовать- termios = unix, файловый дескриптор в стиле posix
Curses = портальная терминальная обработка (которая является специфической консольной парадигмой, а не универсальной)
Python обертывает определенные классы ввод, который может исходить с клавиатуры: например, sys.stdin для консоли inupt.
Но попытка получить универсальный ввод с клавиатуры - это очень общая проблема, которая по своей сути зависит от платформы.
Вот как это можно сделать в 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's no ++ in python number += 1 #wait half a second time.sleep(0.5)