Search code examples
pythonpynput

How to pause a pynput event listener


I am trying to make a program that will read the user's inputs and if it detects a certain key combination, it will type a special character. Currently I am testing and I want the script to just output a '+' after each character that the user types. I am using the pynput event listener to determine if a key was pressed and using a 'Pause' variable so that the output of the '+' doesn't cause the event listener to make an infinite loop. The problem is that the event listener is going into an infinite loop anyway and I am not sure why.

Current typed output after each key press: +++++++++++++++++++...

Desired typed output after each key press: +

Current console output after each key press:
pause is False
getting pressed
getting released
['f']
paused
send outputs
unpaused
pause is False
getting pressed
getting released
['+']
paused
send outputs
unpaused
pause is False
getting pressed
getting released
['+']
paused
send outputs
unpaused
pause is False
getting pressed
getting released
...

Desired console output after each key press:
pause is False
getting pressed
getting released
['f']
paused
send outputs
pause is True
unpaused

import pynput
import time
from pynput.keyboard import Key, Listener, Controller
keyboardOut = Controller()
PressedKeys = []
ReleasedKeys = []
Pause = False
def on_press(key):
    global PressedKeys, ReleasedKeys, Pause
    print("pause is "+str(Pause))
    if Pause == False:
        print("getting pressed")
        PressedKeys.append(key)
    else:
        return
    


def on_release(key):
    global PressedKeys, ReleasedKeys, Pause
    if Pause == False and len(PressedKeys) > 0:
        print("getting released")
        ReleasedKeys.append(key)
        test_frame()
    else:
        return

def test_frame():
    global Pause
    print(PressedKeys)
    Pause = True
    print("paused")
    print("send outputs")
    keyboardOut.press('+')
    keyboardOut.release('+')
    PressedKeys.clear()
    ReleasedKeys.clear()
    Pause = False
    print("unpaused")
    time.sleep(1)
    
# Collect events until released 
with Listener(
        on_press=on_press,
        on_release=on_release) as listener:
    listener.join() 

How can I fix my code to *actually* pause the event listener. I am new to python, so I might just not understand how to update global variables correctly.

Solution

  • You have to stop the listener before using the keyboard controller. I hope this code helps out, I tried to get as close to what I thought you were looking for.

    code:

    from pynput import keyboard
    from time import sleep
    
    KeyboardOut = keyboard.Controller()
    pressed_keys = []
    released_keys = []
    
    def on_press(key):
        try:
            pressed_keys.append(format(key.char))
        except AttributeError:
            print('special key {0} pressed'.format(
                key))
    
    def on_release(key):
        if len(pressed_keys) > 0:
            released_keys.append(format(key))
            test_frame()
            return False
        if key == keyboard.Key.esc:
            # Stop listener
            return False
    
    def test_frame():
        print('\n\n'+str(pressed_keys))
        print('paused')
        print('send outputs')
        KeyboardOut.press('+')
        KeyboardOut.release('+')
        pressed_keys.clear()
        released_keys.clear()
        with keyboard.Listener(
            on_press=on_press,
            on_release=on_release) as listener:
            listener.run()
        print('unpaused')
        sleep(1)
        return True
    
    # Collect events until released
    with keyboard.Listener(
            on_press=on_press,
            on_release=on_release) as listener:
        listener.run()