74

コンソールのpythonアプリからキーボードをポーリングするにはどうすればよいですか? 具体的には、他の多くの I/O アクティビティ (ソケットの選択、シリアル ポート アクセスなど) の最中に、これに似たようなことをしたいと考えています。

while True:
    # 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 への移植性も悪くありません。

4

12 に答える 12

39

標準的なアプローチは、selectモジュールを使用することです。

ただし、これは Windows では機能しません。そのために、msvcrtモジュールのキーボード ポーリングを使用できます。

多くの場合、これは複数のスレッドで行われます。「監視」対象のデバイスごとに 1 つと、デバイスによって中断される必要がある可能性のあるバックグラウンド プロセスです。

于 2008-11-15T17:09:00.650 に答える
22

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)
于 2010-08-19T17:12:50.163 に答える
17

わかりました。コメントに解決策を投稿しようとして失敗したので、これが私が言おうとしていたことです。次のコードを使用して、ネイティブPython(Windowsでは、他の場所ではありません)から必要なことを正確に実行できました。

import msvcrt 

def kbfunc(): 
   x = msvcrt.kbhit()
   if x: 
      ret = ord(msvcrt.getch()) 
   else: 
      ret = 0 
   return ret
于 2008-11-20T00:32:05.310 に答える
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
于 2009-09-20T01:47:23.303 に答える
16

これらの答えはどれもうまくいきませんでした。このパッケージ、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()
于 2016-12-11T06:31:18.320 に答える
6

コメントから:

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 True:
    x = kbfunc()

    if x != 0:
        print "Got key: %d" % x
    else:
        time.sleep(.01)
于 2008-11-15T23:53:49.057 に答える
5

http://home.wlu.edu/~levys/software/kbhit.pykbhitでのクロスプラットフォーム実装に出くわしました(無関係なコードを削除するために編集を行いました):

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まで戻り続けます。

于 2019-04-15T15:13:56.460 に答える
4

pygameがこれを処理する方法を見て、いくつかのアイデアを盗むことができます。

于 2008-11-15T03:49:45.193 に答える