I am working on a snippet that requires user interaction: either an Esc press or a Ctrl+Shift press.
I am struggling with combining Ctrl+Shift though. The below code works fine with the Esc button. However, when pressing Ctrl+Shift initially (before pressing Esc) it doesn't print anything, while after having pressed Esc at least once, it works for Shift but not for Ctrl- which is not what I intended. How can I bind Ctrl and Shift together?
from pynput import keyboard
COMBINATIONS = [
{ keyboard.Key.shift, keyboard.Key.ctrl },
{ keyboard.Key.esc }
]
# The currently active modifiers
current = set()
def execute():
print ("Pressed!")
def on_press(key):
if any([key in COMBO for COMBO in COMBINATIONS]):
current.add(key)
if any(all(k in current for k in COMBO) for COMBO in COMBINATIONS):
execute()
def on_release(key):
try:
current.remove(key)
except KeyError:
pass
with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
If you put a print(key) at the start of on_press, you'll see that the CTRL key generates either a ctrl_l or ctrl_r key (depending on which one you've pressed), not a ctrl key.
So you either have to handle either of them, ending up with some monstrous any/all/any code snippet, or just translate at the top:
if key == keyboard.Key.ctrl_l or key == keyboard.Key.ctrl_r:
key = keyboard.Key.ctrl
A version which handles this with a translation function xlate() (for CTRL and SHIFT keys, since the latter appear to generate shift/shift_r), as well as detecting releases of keys, can be seen below:
from pynput import keyboard
COMBINATIONS = [
{ keyboard.Key.shift, keyboard.Key.ctrl },
{ keyboard.Key.esc }
]
current = set()
def execute():
print ("Pressed!")
def xlate(key):
if key == keyboard.Key.ctrl_l or key == keyboard.Key.ctrl_r:
return keyboard.Key.ctrl
if key == keyboard.Key.shift_l or key == keyboard.Key.shift_r:
return keyboard.Key.shift
return key
def on_release(key):
key = xlate(key)
if key in current:
current.remove(key)
def on_press(key):
#print(key) # for debugging purposes.
key = xlate(key)
if any([key in COMBO for COMBO in COMBINATIONS]):
current.add(key)
if any(all(k in current for k in COMBO) for COMBO in COMBINATIONS):
execute()
with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
Related
I have problem with Keys in pynput
on_press function should check if button pressed i 'h' but it gives error
from pynput.keyboard import Key, Listener
def on_press(key):
print(key)
if key == Key.h:
print('done')
def on_release(key):
print('{0} release'.format(key))
if key == Key.esc:
return False
# Collect events until released
with Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
the error is created by the if key == Key.h: statement inside the on_press function. When i comment this out, it works without error.
So this works:
from pynput.keyboard import Key, Listener
def on_press(key):
print(key)
# if key == Key.h: # <-- cause the error
# print('done') # <-- cause the error
def on_release(key):
print('{0} release'.format(key))
if key == Key.esc:
return False
# Collect events until released
with Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
returns (when i press various buttons etc):
'h'
'h' release
Key.alt_l
Key.tab
Key.alt_l release
Key.tab release
Key.alt_l
Key.tab
Key.alt_l release
It looks like the examples use a try-except block for the equivalent on_press function that you have created.
Here is the link to how it works: https://pynput.readthedocs.io/en/latest/keyboard.html
When i replace the function with this is performs well:
def on_press(key):
print(key)
try:
if key == Key.h:
print('done')
except:
print('something else')
and i get this:
'h'
something else
'h' release
'i'
something else
'i' release
Key.alt_l
something else
Key.tab
something else
Key.alt_l release
Key.tab release
Key.alt_l
You can see that the exception needs to be handled (many time) from the above, which is why the code in the question was broken.
your way to solve this problem doesn't work or maybe it's mine misunderstanding. When i tried to comment every print, to only print 'done' after checking if pressed key is 'h' it doesn't work
def on_press(key):
try:
if key == Key.h:
print('done')
except:
return
def on_release(key):
#print('{0} release'.format(key))
if key == Key.esc:
return False
If I press ctrl and alt at the same time, my program does nothing. I want if I press ctrl and alt at the same time python will automatically refresh the page 100 times.
Does anyone know why this isn't working and what I need to change?
from pynput import keyboard
def on_press(key):
if key == keyboard.Key.esc:
return False # stop listener
try:
k = key.char # single-char keys
except Exception as ex:
k = key.name # other keys
if k in ['ctl'+'alt']: # keys of interest
# self.keys.append(k) # store it in global-like variable
print('Key pressed: ' + k)
listener = keyboard.Listener(on_press=on_press)
listener.start() # start to listen on a separate thread
listener.join() # remove if main thread is polling self.keys
I have been testing your example and it seems that the library distinguishes between left and right 'Ctrl' and 'Alt'.
You should also note that only ONE KEY is detected, so the expression 'if k in ['ctl'+'alt']:' will never be TRUE.
If you change it to 'if k in ['ctrl_l', 'alt_l']:' (note that I changed the names of the keys as I said before that every key is different) at least one of them will be recognised. The approach given to achieve your goal is not the right one. Check this approach or something like this:
from pynput import keyboard
# The key combination to check
COMBINATION = {keyboard.Key.ctrl_l, keyboard.Key.alt_l}
# The currently active modifiers
current = set()
def on_press(key):
if key in COMBINATION:
current.add(key)
if all(k in current for k in COMBINATION):
print('PRESSED')
if key == keyboard.Key.esc:
listener.stop()
def on_release(key):
try:
current.remove(key)
except KeyError:
pass
with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
I trying to make a code to wait until i press [ or ], where [ make a specific thing and ] make other.
But i can't cuz i need to make both waits in the same time.
import keyboard
import threading
def listener():
keyboard.wait(']')
print('] pressed')
while True:
threading.Thread(target=listener()).start()
keyboard.wait('[')
print('[ pressed')
print('\nLoop\n')
This way the code wait ] and only when i press this key pass to next key [
I want to press any key and return print('key pressed') regardless of the order in which I press
I saw some listeners in web and i found a code that solved my problem
from pynput import keyboard
def on_press(key):
if key == keyboard.Key.esc:
return False
try:
k = key.char
except:
k = key.name
if k == '[':
print('Key pressed: ' + k)
print('continuing...')
if k == ']':
print('Key pressed: ' + k)
print('stoping')
return False
Link: https://stackoverflow.com/a/43106497/15785950
I want to write a program which counts, how often a key is pressed on my keyboard (e.g. per day). I can use Pynput to recognize a certain keypress, but I'm struggling with the counting part. Here's what I got so far:
from pynput.keyboard import Key, Listener
i = 0
def on_press(key, pressed):
print('{0} pressed'.format(
key))
if pressed({0}):
i = i + 1
def on_release(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()
That executes the following error:
TypeError: on_press() missing 1 required positional argument: 'pressed'
I also don't know how to seperate all 26 letters and am not really sure what to do now...does anyone have an idea?
I'm trying to figure this exact problem out myself. To answer what the error wants, it wants you to define the parameter "pressed" in your arguments passed to on_press.
ex.
def on_press(key, pressed=0):
print('{0} pressed'.format(
key))
if pressed({0}):
i = i + 1
your i = 0 above that block is out of scope for the on_press block, and therefore cannot be used.
The problem I'm having is, I can get it to count the keystrokes recursively, however it doesn't stop and goes to the max recursion depth with just one keystroke!
I'll reply again if I make any progress. Good luck to you as well!
--- I figured it out! ---
The following link to another StackOverflow post led me in the right direction:
Checking a specific key with pynput in Python
Here's my code. It will display the character typed and increment the count of keys typed:
from pynput.keyboard import Key, Listener
strokes = 0
def on_press(key):
if key == Key.esc:
return False
print('{0} pressed'.format(
key))
global strokes
strokes += 1
print(strokes)
with Listener(
on_press=on_press) as listener:
listener.join()
I hope this helps!
from pynput import keyboard
c=0
with keyboard.Events() as events:
for event in events:
if event.key == keyboard.Key.esc:
break
elif (str(event)) == "Press(key='1')":
c+=1
print(c)
You can use any keys inside "Press(key='1')" like "Press(key='2')" , "Press(key='q')"
I've already looked at previous post, but can't find something that works...
Globally my goal : a script in python that if I press ‘k’ it will start to hold ‘k’ until I press escape.
But the problem is : it doesn’t hold ‘k’ and I don’t know why
If someone might help I’d be glad,
Thank you
from pynput import keyboard
import pyautogui
def on_press(key):
try:
print('alphanumeric key {0} pressed'.format(
key.char))
if key.char == 'k':
return False
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
def listening_k():
with keyboard.Listener(
on_press=on_press) as listener:
listener.join()
return True
def listening_esc():
with keyboard.Listener(
on_release=on_release) as listener:
listener.join()
return True
def hold_key(key):
while listening_k() == True :
pyautogui.keyDown(key)
if listening_esc() == True :
break
hold_key('k')
You can make it simple by having a variable that holds the state (boolean value) if 'k' key is on press. Make it True anytime you press 'k' key and False for pressing 'esc' key.