Listening for specific keys with pynput

人走茶凉 提交于 2020-01-23 17:42:48

问题


I'd like my code to listen for user input, and do something if key c is pressed, and something else if key v is pressed.

I've managed to do it using global, but it feels like an ugly hack :

from pynput import keyboard

def on_press(key):
    try:
        global user_input 
        if key.char == "c":
            user_input = "c"
        elif key.char == "v":
            user_input == "v"
    except AttributeError:
        pass

def on_release(key):
    if key == keyboard.Key.esc:
        # Stop listener
        return False

def wait_for_user_input():
    global user_input
    listener = keyboard.Listener(on_press=on_press, on_release=on_release)
    listener.start()
    user_input = 0
    while user_input == 0:
        time.sleep(0.5)
        if user_input == "c":
            # do something
            listener.stop()
            break
        elif user_input == "v":
            # do something else
            listener.stop()
            break
    # other stuff

wait_for_user_input()

Is there a better way to do it ? (Maybe by having the listener stop & return the values c or v in on_press() ? If so, I couldn't find how to do it.)

Also : since wait_for_user_input() will be called multiple times, would it be better to not start and stop the listener repetitively, and instead have it start once and stop once ?


回答1:


You can put functions directly in on_press and then you don't need while loop. You may need only listener.join() which will wait for listener.stop()

from pynput import keyboard

def on_press(key):
    try:
        if key.char == "c":
            # do something
            return False  # Stop listener
        elif key.char == "v":
            # do something else
            return False  # Stop listener
    except AttributeError as ex:
        print(ex)

def on_release(key):
    if key == keyboard.Key.esc:
        # Stop listener
        return False

def wait_for_user_input():
    listener = keyboard.Listener(on_press=on_press, on_release=on_release)
    listener.start()
    listener.join() # wait till listener will stop
    # other stuff        

EDIT:

If you need run functions which result you need in other functions then you may stay with global user_input but you can write it little different.

from pynput import keyboard

def on_press(key):
    global user_input

    try:
        if key.char in ("c", "v"):
            user_input = key.char
            return False  # Stop listener
    except AttributeError as ex:
        print(ex)

def on_release(key):
    if key == keyboard.Key.esc:
        return False  # Stop listener

def wait_for_user_input():
    listener = keyboard.Listener(on_press=on_press, on_release=on_release)
    listener.start()
    listener.join() # wait till listener will stop

    if user_input == "c":
        # do something
    elif user_input == "v":
        # do something else
    else:
        print('You pressed ESC ?')

EDIT: If you use Windows then you could use msvcrt.getch which gives shorter and nicer code.

from msvcrt import getch

def wait_for_user_input():

    while True:
        user_input = getch()
        if user_input == "c":
            print('selected: c')
            break
        elif user_input == "v":
            print('selected: v')
            break
        elif user_input == escape:
            print('You pressed ESC ?')
            break

wait_for_user_input()

For Linux should be similar function getch() but with longer code.

See also module getch but I didn't check it.



来源:https://stackoverflow.com/questions/57262917/listening-for-specific-keys-with-pynput

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!