如何从控制台python app轮询键盘?具体来说,我想在许多其他I / O活动(套接字选择,串行端口访问等)中做类似的事情:
while 1:
# doing amazing pythonic embedded stuff
# ...
# periodically do a non-blocking check to see if
# we are being told to do something else
x = keyboard.read(1000, timeout = 0)
if len(x):
# ok, some key got pressed
# do something
在Windows上执行此操作的正确pythonic方法是什么?此外,Linux的可移植性也不错,但并不是必需的。
答案 0 :(得分:31)
标准方法是使用select模块。
但是,这在Windows上不起作用。为此,您可以使用msvcrt模块的键盘轮询。
通常,这是通过多个线程完成的 - 每个设备被“监视”一个加上可能需要被设备中断的后台进程。
答案 1 :(得分:16)
import sys
import select
def heardEnter():
i,o,e = select.select([sys.stdin],[],[],0.0001)
for s in i:
if s == sys.stdin:
input = sys.stdin.readline()
return True
return False
答案 2 :(得分:16)
使用curses模块的解决方案。打印与按下的每个键对应的数值:
import curses
def main(stdscr):
# do not wait for input when calling getch
stdscr.nodelay(1)
while True:
# get keyboard input, returns -1 if none available
c = stdscr.getch()
if c != -1:
# print numeric value
stdscr.addstr(str(c) + ' ')
stdscr.refresh()
# return curser to start position
stdscr.move(0, 0)
if __name__ == '__main__':
curses.wrapper(main)
答案 3 :(得分:14)
好的,因为我试图在评论中发布我的解决方案失败了,这就是我想说的。我可以使用以下代码完成我想要的原生Python(在Windows上,而不是其他任何地方):
import msvcrt
def kbfunc():
x = msvcrt.kbhit()
if x:
ret = ord(msvcrt.getch())
else:
ret = 0
return ret
答案 4 :(得分:11)
这些答案都不适合我。这个包pynput完全符合我的需要。
https://pypi.python.org/pypi/pynput
from pynput.keyboard import Key, Listener
def on_press(key):
print('{0} pressed'.format(
key))
def on_release(key):
print('{0} release'.format(
key))
if key == Key.esc:
# Stop listener
return False
# Collect events until released
with Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
答案 5 :(得分:5)
你可能会看看pygame如何处理这个问题来窃取一些想法。
答案 6 :(得分:5)
来自评论:
import msvcrt # built-in module
def kbfunc():
return ord(msvcrt.getch()) if msvcrt.kbhit() else 0
感谢您的帮助。我最终编写了一个名为PyKeyboardAccess.dll的C DLL并访问了crt conio函数,导出了这个例程:
#include <conio.h>
int kb_inkey () {
int rc;
int key;
key = _kbhit();
if (key == 0) {
rc = 0;
} else {
rc = _getch();
}
return rc;
}
我使用ctypes模块(内置于python 2.5中)在python中访问它:
import ctypes
import time
#
# first, load the DLL
#
try:
kblib = ctypes.CDLL("PyKeyboardAccess.dll")
except:
raise ("Error Loading PyKeyboardAccess.dll")
#
# now, find our function
#
try:
kbfunc = kblib.kb_inkey
except:
raise ("Could not find the kb_inkey function in the dll!")
#
# Ok, now let's demo the capability
#
while 1:
x = kbfunc()
if x != 0:
print "Got key: %d" % x
else:
time.sleep(.01)
答案 7 :(得分:1)
我用这个来检查按键,可以简化得多:
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
import curses, time
def main(stdscr):
"""checking for keypress"""
stdscr.nodelay(True) # do not wait for input when calling getch
return stdscr.getch()
while True:
print("key:", curses.wrapper(main)) # prints: 'key: 97' for 'a' pressed
# '-1' on no presses
time.sleep(1)
虽然curses没有在Windows上工作,但是有一个&#39; unicurses&#39;据说可能在Linux,Windows,Mac上工作,但是我无法使用它
答案 8 :(得分:0)
If you combine time.sleep, threading.Thread, and sys.stdin.read you can easily wait for a specified amount of time for input and then continue, also this should be cross-platform compatible.
t = threading.Thread(target=sys.stdin.read(1) args=(1,))
t.start()
time.sleep(5)
t.join()
You could also place this into a function like so
def timed_getch(self, bytes=1, timeout=1):
t = threading.Thread(target=sys.stdin.read, args=(bytes,))
t.start()
time.sleep(timeout)
t.join()
del t
Although this will not return anything so instead you should use the multiprocessing pool module you can find that here: how to get the return value from a thread in python?
答案 9 :(得分:0)
我在http://home.wlu.edu/~levys/software/kbhit.py遇到了kbhit
的跨平台实现(进行编辑以删除不相关的代码):
import os
if os.name == 'nt':
import msvcrt
else:
import sys, select
def kbhit():
''' Returns True if a keypress is waiting to be read in stdin, False otherwise.
'''
if os.name == 'nt':
return msvcrt.kbhit()
else:
dr,dw,de = select.select([sys.stdin], [], [], 0)
return dr != []
请确保read()
个等待字符-函数将一直返回True
,直到您这样做!