파이썬에서 키 누름을 감지합니까?


106

나는 파이썬에서 스톱워치 유형 프로그램을 만들고 있는데 키가 눌 렸는지 감지하는 방법을 알고 싶습니다 (예 : 일시 정지의 경우 p, 중지의 경우 s). 나는 그것을 기다리는 raw_input과 같은 것이되고 싶지 않습니다. 실행을 계속하기 전에 사용자의 입력. 누구나 while 루프에서 이것을 수행하는 방법을 알고 있습니까?

또한이 크로스 플랫폼을 만들고 싶지만 가능하지 않은 경우 주요 개발 대상은 Linux입니다.


OS X 용 stackoverflow.com/a/47197390/5638869 는 Python 2 및 3에서 작동합니다
neoDev

답변:


71

Python에는 많은 기능 이있는 키보드 모듈이 있습니다. 다음 명령을 사용하여 설치하십시오.

pip3 install keyboard

그런 다음 다음과 같은 코드에서 사용하십시오.

import keyboard  # using module keyboard
while True:  # making a loop
    try:  # used try so that if user pressed other than the given key error will not be shown
        if keyboard.is_pressed('q'):  # if key 'q' is pressed 
            print('You Pressed A Key!')
            break  # finishing the loop
    except:
        break  # if user pressed a key other than the given key the loop will break

2
Linux에 대해서는 잘 모르겠지만 Windows에서 작동합니다.

74
keyboard분명히 리눅스에서 루트가 필요합니다 : /
Inaimathi

이 솔루션을 시도했지만 설치 후 모듈을 가져 오려고하면 "ImportError : No module named 'keyboard'"가 표시되어 작동하지 않습니다. GitHub 리포지토리를 확인했고 관련 문제를 찾았 지만 문제 가 해결되지 않았습니다. 그런 다음 리포지토리를 다운로드하고 일부 예제를 실행하려고 시도했지만 @Inaimathi가 이전에 언급했듯이 "ImportError : You must be root to use this library on linux"가 표시됩니다. 분명히 파이썬으로 키보드를 관리하는 완전한 모듈처럼 보이지만 루트의 요구 사항은 크게 부족합니다. (
Ivanhercaz

3
"X에 의존하는 것을 피하기 위해 Linux 부분은 원시 장치 파일 (/ dev / input / input *)을 읽지 만 루트가 필요합니다."
jrouquie

8
나는 왜 시도가되는지 모르겠다 : 예외 : 유용하다.
TypicalHog

49

창문에 있고 작동하는 답을 찾기 위해 고군분투하는 사람들을 위해 여기 내 것입니다 : 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()

위의 기능은 누르는 키를 인쇄하고 'esc'키를 놓을 때 작업을 시작합니다. 더 다양한 사용법을 위해 키보드 설명서가 여기 에 있습니다.

Markus von Broady 는 다음과 같은 잠재적 인 문제를 강조했습니다.이 답변은 현재 창에서이 스크립트를 활성화 할 필요가 없습니다. 창에 대한 해결책은 다음과 같습니다.

from win32gui import GetWindowText, GetForegroundWindow
current_window = (GetWindowText(GetForegroundWindow()))
desired_window_name = "Stopwatch" #Whatever the name of your window should be

#Infinite loops are dangerous.
while True: #Don't rely on this line of code too much and make sure to adapt this to your project.
    if current_window == desired_window_name:

        with Listener(
            on_press=on_press,
            on_release=on_release) as listener:
            listener.join()

7
@ nimig18 ... 루트 :)를 필요로하지 않습니다
CZ

1
이 솔루션에는 문제가 있습니다 (대안이 확실하지 않음) : 키를 적용하기 위해 콘솔 창 내에서 키를 누를 필요가 없습니다. ESC를 누를 때까지 작업을 수행하는 스크립트가 있지만 다른 프로그램에서 누르는 경우를 상상해보십시오.
Markus von Broady

1
@MarkusvonBroady 나는 win32gui가 그것을 해결하기에 충분할 것이라고 생각하며, 적어도 Windows 사용자에게 잠재적으로 해결할 수있는 방식으로 내 대답을 편집했습니다.
Mitrek

@Mitrek 나는 이것을 시도했지만 내 코드는 더 이상 실행을 중지하고 여기에 갇혀 있습니다. input ()처럼 작동합니다. 셀레늄, 파이어 폭스에서 실행되는 코드가 있지만이 시퀀스가 ​​발생하자마자 추가 작업이 없습니다.
Lakshmi Narayanan

1
그것은 리눅스와 윈도우 모두에서 작동하기 때문에 받아 들여진 대답
이어야했다

31

OP가 raw_input에 대해 언급했듯이-이는 그가 cli 솔루션을 원한다는 것을 의미합니다. Linux : curses 는 원하는 것입니다 (Windows PDCurses). Curses는 CLI 소프트웨어를위한 그래픽 API로, 주요 이벤트를 감지하는 것 이상을 달성 할 수 있습니다.

이 코드는 새 줄을 누를 때까지 키를 감지합니다.

import curses
import os

def main(win):
    win.nodelay(True)
    key=""
    win.clear()                
    win.addstr("Detected key:")
    while 1:          
        try:                 
           key = win.getkey()         
           win.clear()                
           win.addstr("Detected key:")
           win.addstr(str(key)) 
           if key == os.linesep:
              break           
        except Exception as e:
           # No input   
           pass         

curses.wrapper(main)

이것은 정말 좋습니다. 그것을 발견하기 전에 영원히 찾아야했다. 주위를 해킹하는 것보다 훨씬 깨끗해 보입니다 termios...
Hugh Perkins

5
import os예제를 종료하려면 추가해야합니다 .
malte

win.nodelay(False)대신 수행하면 True초당 백만 개의 예외가 생성되지 않습니다.
Johannes Hoff

25

keyboard모듈로 할 수있는 일이 더 있습니다 .

다음은 몇 가지 방법입니다.


방법 # 1 :

기능 사용 read_key():

import keyboard

while True:
    if keyboard.read_key() == "p":
        print("You pressed p")
        break

p를 누르면 루프가 끊어 집니다.


방법 # 2 :

기능 사용 wait:

import keyboard

keyboard.wait("p")
print("You pressed p")

p눌렀을 때 코드 를 누르고 계속할 때까지 기다립니다 .


방법 # 3 :

기능 사용 on_press_key:

import keyboard

keyboard.on_press_key("p", lambda _:print("You pressed p"))

콜백 함수가 필요합니다. _키보드 기능이 해당 기능에 키보드 이벤트를 반환하기 때문에 사용했습니다 .

일단 실행되면 키를 누르면 기능이 실행됩니다. 다음 줄을 실행하여 모든 후크를 중지 할 수 있습니다.

keyboard.unhook_all()

방법 # 4 :

이 방법은 이미 user8167727 에 의해 답변 되었지만 그들이 만든 코드에 동의하지 않습니다. 함수를 사용 is_pressed하지만 다른 방식으로 사용합니다.

import keyboard

while True:
    if keyboard.is_pressed("p"):
        print("You pressed p")
        break

p누르면 루프가 끊어 집니다.


노트:

  • keyboard 전체 OS에서 키 누르기를 읽습니다.
  • keyboard 리눅스에서 루트 필요

11
키보드 모듈 사용의 가장 큰 단점은 ROOT 사용자로 실행해야한다는 것입니다. 이것은 내 코드에서 모듈을 verboten하게 만듭니다. 키를 눌렀는지 여부를 폴링하기 위해 루트 권한이 필요하지 않습니다. 문서를 읽고 모듈에서 제한이 종료되는 이유를 이해했습니다. 그러나 필요한 모든 것이 키를 폴링하는 것이라면 다른 곳을 살펴보십시오.
muman

매우 유용한 정보를 공유했습니다. keyboard.wait()두 개 이상의 키를 기다리는 데 사용할 수 있는지 알고 싶었고 둘 중 하나를 눌렀을 때 계속할 수 있는지 알고 싶었습니다.
Preetkaran Singh

@PreetkaranSingh wait()는이 기능을 제공하지 않습니다. keyboard.read_key()while 루프에 포함 된 if 조건과 함께 사용해야 합니다. 방법 # 1
Black Thunder

감사합니다 선생님! 당신은 되거 싶습니다 suppress의 키워드 사용 keyboard.read_key()을 사용하지 않을 때 .... 때,
Preetkaran 싱

내가하고자하지만 난 억제 인자에 대한 충분한 정보가없는 @PreetkaranSingh
블랙 천둥

14

들어 윈도우 당신은 사용할 수 있습니다 msvcrt다음과 같이 :

   import msvcrt
   while True:
       if msvcrt.kbhit():
           key = msvcrt.getch()
           print(key)   # just to show the result

7
msvcrt는 Windows 전용 모듈입니다.
Dunatotatos

1
저는 실제로 pynput을 사용합니다. 더 나은 답이 될 수 있습니다.
Benjie

OS X에서 작동하는 pynput (Linux에 대해 알지 못함)이 작동하려면 루트로 실행해야합니다. 그것은 일부 사람들에게는 시작이 아닐 수 있습니다.
Gabe Weiss

나는 '크로스 플랫폼'또는 '리눅스'에 대한 질문이라고 맹세 할 수 있었다 ...
Aaron Mann

10

이 코드를 사용하여 누른 키를 찾으십시오.

from pynput import keyboard

def on_press(key):
    try:
        print('alphanumeric key {0} pressed'.format(
            key.char))
    except AttributeError:
        print('special key {0} pressed'.format(
            key))

def on_release(key):
    print('{0} released'.format(
        key))
    if key == keyboard.Key.esc:
        # Stop listener
        return False

# Collect events until released
with keyboard.Listener(
        on_press=on_press,
        on_release=on_release) as listener:
    listener.join()

하지만 여기에 문제가 있습니다. 저는 macOS를 사용하고 있으며 pynput과 키보드를 별도로 설치했으며 프로그램은 오류없이 실행되지만 (python 셸에서) 특수 키만 감지 할 수 있습니다. 영숫자 키는 감지되지 않으며 반대로 쉘에 코드를 작성하는 것처럼 간주됩니다. 무엇이 문제인지 알고 있습니까?
Dario Deniz Ergün 2019

셸에서 동일한 코드가 저에게 효과적이었습니다. 확인해주세요. 키보드 패키지에는이 코드가 필요하지 않습니다.
Manivannan Murugavel

1
이것은 키보드 lib에 루트가 필요하기 때문에 Linux로 이동하는 방법입니다.
David

1
이 솔루션은 모든 키 입력 을 감지 합니다 . 다른 터미널 창에서도 발생합니다. 불행히도 이것은 가능한 사용 사례를 심각하게 제한합니다.
Serge Stroobandt

6

PyGame을 사용하여 창이 있으면 주요 이벤트를 얻을 수 있습니다.

편지의 경우 p:

import pygame, sys
import pygame.locals

pygame.init()
BLACK = (0,0,0)
WIDTH = 1280
HEIGHT = 1024
windowSurface = pygame.display.set_mode((WIDTH, HEIGHT), 0, 32)

windowSurface.fill(BLACK)

while True:
    for event in pygame.event.get():
        if event.key == pygame.K_p: # replace the 'p' to whatever key you wanted to be pressed
             pass #Do what you want to here
        if event.type == pygame.locals.QUIT:
             pygame.quit()
             sys.exit()

2

그래서 저는이 게시물을 기반으로 .. 종류의 게임을 만들었습니다 (msvcr 라이브러리 및 Python 3.7 사용).

다음은 누른 키를 감지하는 게임의 "주요 기능"입니다.

# Requiered libraries - - - -
import msvcrt
# - - - - - - - - - - - - - -


def _secret_key(self):
    # Get the key pressed by the user and check if he/she wins.

    bk = chr(10) + "-"*25 + chr(10)

    while True:

        print(bk + "Press any key(s)" + bk)
        #asks the user to type any key(s)

        kp = str(msvcrt.getch()).replace("b'", "").replace("'", "")
        # Store key's value.

        if r'\xe0' in kp:
            kp += str(msvcrt.getch()).replace("b'", "").replace("'", "")
            # Refactor the variable in case of multi press.

        if kp == r'\xe0\x8a':
            # If user pressed the secret key, the game ends.
            # \x8a is CTRL+F12, that's the secret key.

            print(bk + "CONGRATULATIONS YOU PRESSED THE SECRET KEYS!\a" + bk)
            print("Press any key to exit the game")
            msvcrt.getch()
            break
        else:
            print("    You pressed:'", kp + "', that's not the secret key(s)\n")
            if self.select_continue() == "n":
                if self.secondary_options():
                    self._main_menu()
                break

porgram의 전체 소스 코드를 원하면 여기에서 보거나 다운로드 할 수 있습니다.

비밀 키 게임 (GitHub)

(참고 : 비밀 키 누르기 : Ctrl + F12)

이 정보를 참조하러 오는 사람들에게 모범이되고 도움이되기를 바랍니다.



1
key = cv2.waitKey(1)

이것은 openCV 패키지에서 가져온 것입니다. 기다리지 않고 키 누름을 감지합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.