0

I want to detect if a keypress was executed programmatically (not by user's physical press). Is there any way to do this?

import mouse
import keyboard
import time


keyboard.press("a")

if keyboard.is_pressed('a'):
    print ("pressed")

I assume 'is_pressed' in the code above only detects actual input from user hence it wouldn't show print ("pressed"). All I could come up with to solve this is the code below which works just fine for my intention but I want to know if there's a better optimized way.

import mouse
import keyboard
import time
    
    
keyboard.press("a")
keyboard_a = True

keyboard.press("b")
keyboard_b = True
    
if keyboard_a:
    print ("a pressed")

if keyboard_b:
    print ("b pressed")    
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
kerz
  • 67
  • 6
  • Do you mean - you want to detect if a keypress event was issued from some code pushing a key-press event, and not from a keyboard device? – JimmyNJ Dec 24 '22 at 14:36
  • Oh, hold on. You think `print("pressed")` issues key-press events to the console to write the word `pressed`, is that it? – JimmyNJ Dec 24 '22 at 14:38
  • @JimmyNJ the first one, the way to detect if the key press event is triggered progammatically – kerz Dec 24 '22 at 15:02
  • To be clear, it is *your own code* that is emitting the programmatic key-presses that you want to detect? You should change that code, not the code that handles the key-press events. It is very strange for you to emit programmatic key-presses from the same program that is listening for those key-presses; there are much better ways for a program to send data to another part of the same program. – kaya3 Dec 25 '22 at 01:16

2 Answers2

1

It is not possible to distinguish between key press events that are triggered programmatically and those that are triggered by user input. The same is true for readchar, msvcrt, or keyboard libraries.

So, the library provides a way to detect and respond to key press events, regardless of their origin. Hence, your approach with a flag is good.

I don't know your precise aim, but maybe you would prefer to use send and a register event like this

import keyboard
import threading

is_programmatic = False

# Define a function to be called when a specific key is pressed
def on_key_press(keyEvent):
    global is_programmatic

    if keyEvent.name == 'a':
        if is_programmatic:
            print("Key press event triggered programmatically")
        else:
            print("Key press event triggered by user input")
    
        is_programmatic = False

# Register listener
keyboard.on_press(on_key_press)

# Start keyboard listener
keyboard.wait()

# or start a thread with the listener (you may want to sleep some seconds to wait the thread)
thread = threading.Thread(target=keyboard.wait)
thread.start()

and to issue the event

is_programmatic = True
keyboard.send("a")
  • the code you provided doesnt work for some reason. – kerz Dec 24 '22 at 15:15
  • @kerz - provide an error message so the author can try to help. – JimmyNJ Dec 24 '22 at 15:23
  • theres no error message it just keeps idling. i think its because the 'key' argument in on_key_press takes more than just a key input. i tried print (key) and it prints'KeyboardEvent(a down)', not just 'a' – kerz Dec 24 '22 at 15:27
  • still haven't figured how to fix this – kerz Dec 24 '22 at 15:30
  • keyboard.wait() function is a blocking function that waits for keyboard events indefinitely the implementation depend on what you have to do. I updated the code with the threaded version. There was also a bug since the variable catched is an event and not the key itself – Giovanni Minelli Dec 25 '22 at 18:19
0

You can create a list and store pressed keys in that list. You can find if a key is pressed by searching that list.

import keyboard

key_pressed = []

keyboard.press("a")
key_pressed.append("a")

keyboard.press("b")
key_pressed.append("b")

keyboard.press("c")
key_pressed.append("c")

#check if a specific key is pressed
if "a" in key_pressed:
    print ("a pressed")

Print all pressed keys:

for key in key_pressed:
    print(key,'pressed')

Print the last pressed key:

print(key_pressed[-1])

You can also create a class to make it easier to use:

import keyboard
class CustomKeyboard():
    def __init__(self):
    self.pressed_keys = []

def press(self, key):
    keyboard.press(key)
    self.pressed_keys.append(key)

def is_pressed_programmatically(self, key):
    if key in self.pressed_keys:
        return True
    return False

Then use it like this:

kb = CustomKeyboard()

kb.press('a')
kb.press('b')

print("did a pressed programmatically?:")
print(kb.is_pressed_programmatically('a'))

print("did z pressed programmatically?:")
print(kb.is_pressed_programmatically('z'))

and here is the output:

is a pressed programmatically?: True

is z pressed programmatically?: False

Soroosh
  • 543
  • 1
  • 4
  • 21
  • i also thought of this as well but just curious if theres a better way – kerz Dec 24 '22 at 15:16
  • @kerz As I know there is not a built-in function in keyboard library. You may also create a class to handle this functionality in a more beautiful way. I will edit my answer and show you how. – Soroosh Dec 25 '22 at 01:53