Comments (28)
Thank you!
The listener does not maintain a list of the currently pressed keys---this would be a new, quite reasonable, feature.
You can however emulate that using the following snippet:
from pynput import keyboard
# The key combination to check
COMBINATION = {keyboard.Key.cmd, keyboard.Key.ctrl}
# 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('All modifiers active!')
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()
This works as expected, with the following caveat: If one of the modifier keys is pressed before the listener is started, it has to be released and pressed again for the program to detect it.
I will update the road map in the wiki.
from pynput.
from pynput import keyboard
from pynput.keyboard import Key
from threading import Thread
import time
COMBINATION = {
Key.down,
Key.up,
Key.left
#Key.right
}
# The key combination to check
# 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('All modifiers active!')
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 was looking for a way to detect multiple keypresses at once, and this seemed to be the answer. The only problem is that, for whatever reason, only two keys can be returned at the same time (with occasional exception). How do I detect 3+ keyboard inputs at once?
from pynput.
from pynput import keyboard
# The key combination to check
COMBINATION = {keyboard.Key.shift, keyboard.Key.ctrl, keyboard.Key.alt, keyboard.KeyCode.from_char('x')}
# 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('All modifiers active!')
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()
keyboard.KeyCode.from_char('x') or its alike works fine for alphanumeric keys.
Please note that the order of keys pressed is important. Beginning with alt and then x works fine while others may not.
In my point of view, this might have something to with system-built-in shortcuts which often combines ctrl, alt and shift. However, without shift, ctrl+alt+x works fine in any order.
Hope the designer (@moses-palmer) for this phenomenal package which can listen/monitor global keyboard events have some view on this!
from pynput.
Sorry to bump this up again, is just a question because maybe I'm misunderstanding something.
I've used your code above for this type of hotkey combination ctrl + c.
It wasn't working, so I fiddled a bit suspecting that maybe the key press wasn't fired properly, instead it was, but the key returned is not the one expected:
In [1]: from pynput import keyboard
In [2]: keyboard.Key.ctrl
Out[2]: <Key.ctrl: <17>>
In [3]: keyboard.Key.ctrl_l
Out[3]: <Key.ctrl_l: <162>>
keyboard.Key.ctrl
is what I set in my script, but keyboard.Key.ctrl_l
is instead what is caught by the listener; with this mismatch the condition to print the message is never met.
Am I wrong assuming that Key.ctrl
should be considered a general alternative for Key.ctrl_l
or Key.ctrl_r
?
I'm on a Windows 7-64bit with Python 3.7
Thank you!
from pynput.
Thank you for your replay, I learn a lot ๐
from pynput.
Hi,
Thanks for the lib
How can I combine your above example with a regular character to create a hotkey?
IE shift+ctrl+alt+x causes some code to execute.
Thanks
from pynput.
@moses-palmer How are you able to modify the current
varialbe from a function. AFAIK, it's not possible to modify global variable from inside a function in python without explicity declaring global
in your function definition.
https://stackoverflow.com/questions/4522786/modifying-a-global-variable-inside-a-function
from pynput.
from pynput.
That explains it, thanks!
Here is a modified version that also prints a message when you release that key combination!
class MockButton:
def __init__(self, *keys):
self.combination = {*keys}
self.currently_pressed = set()
self.is_pressed = False
listener = Listener(on_press=self._on_press, on_release=self._on_release)
listener.start()
def _on_press(self, key):
if key in self.combination:
self.currently_pressed.add(key)
if self.currently_pressed == self.combination:
self.is_pressed = True
print('pressed!')
def _on_release(self, key):
try:
self.currently_pressed.remove(key)
if self.is_pressed and len(self.currently_pressed) == 0:
self.is_pressed = False
print('released!')
except KeyError:
pass
if __name__ == '__main__':
btn = MockButton(Key.alt, Key.ctrl)
input()
from pynput.
You are correct in assuming that Key.ctrl
is supposed to be a generic alternative to Key.ctrl_l
and Key.ctrl_r
.
In the case of comparisons, however, things do get a bit tricky, especially considering keycode_set_1 == keycode_set_2
.
I guess a possible solution is to add a set of alternate key codes for each KeyCode
instance, and override __eq__
and __hash__
. In the mean time, you can use key in (Key.ctrl, Key.ctrl_l, Key.ctrl_r)
when doing comparisons. That would not work for the code in @devxpy 's comment though.
from pynput.
In the mean time, you can use key in (Key.ctrl, Key.ctrl_l, Key.ctrl_r) when doing comparisons. That would not work for the code in @devxpy 's comment though.
Thank you @moses-palmer, I thought so, this is the code I used if anyone needs this. As a small bonus the following code listens only to double pressing of ctrl + c in less than a second:
from pynput import keyboard
import datetime
# The key combinations to check
COMBINATIONS = [
{keyboard.Key.ctrl_l, keyboard.KeyCode(char='c')},
{keyboard.Key.ctrl_r, keyboard.KeyCode(char='c')}
]
# The currently active modifiers
current = set()
tnow = datetime.datetime.now()
tcounter = 0
def on_press(key):
if any([key in comb for comb in COMBINATIONS]):
current.add(key)
if any(all(k in current for k in comb) for comb in COMBINATIONS):
global tnow
global tcounter
tcounter += 1
if datetime.datetime.now() - tnow < datetime.timedelta(seconds=1):
if tcounter > 1:
tcounter = 0
main_function()
else:
tnow = datetime.datetime.now()
if key == keyboard.Key.esc:
listener.stop()
def on_release(key):
try:
current.remove(key)
except KeyError:
pass
def main_function():
print('Main function fired!')
# rest of your code here...
with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
If you have comments on above code to improve it or any suggestions (in particular the rather sloppy global
declare, I'm still learning) please let me know!
Thank you.
from pynput.
Hi @GlassGruber, I tried your code, but for some reason (I am on Windows) my "c" or "v" is like this only when pressed alone. When I have ctrl pressed, I get '\x16' '\x13' and don't match the combination.... @moses-palmer do you have any hint?
from pynput.
On a mac (changing the ctrl to cmd) I get the 'v' as 'โ'
@moses-palmer Is it possible that this is an issue? Or, is there a way to get the correct combination?
from pynput.
Does anyone have any idea how to fix this? @521xueweihan? @devxpy? @moses-palmer? @GlassGruber?
from pynput.
What version do you use? Commit 63aab1a, included in pynput 1.4, introduces a fix for keyboard layout handling, which is especially notable when running the application in a command window.
I have tested the code in @GlassGruber's comment using the master branch, which correctly identified Ctrl + C, and with that commit reverted, which caused your issue with only a non-ASCII key being generated.
Note that this on Windows; the Mac issue is different, and unresolved. Running the test script and printing all characters reveal that all alphanumeric keys are altered. Ctrl + C does work however; perhaps the simple and necessary solution is to add a special case for macOS? Using Cmd already mandates this.
from pynput.
@moses-palmer I've tried the pynput 1.4 and the master.
I've used this: (I also changed 'c' for 'v' and ctrl for cmd on mac)
def on_press(key):
print('KEY', key)
try: print('CHAR', key.char) # letters, numbers et
except: print('NAME', keyboard.KeyCode().from_char(key.name))
On Mac High Sierra - sequence: cmd / v / cmd+v
Both gave me:
KEY Key.cmd
NAME 'cmd'
KEY 'v'
CHAR v
vKEY Key.cmd
NAME 'cmd'
KEY 'โ'
CHAR โ
mainFunction was never fired. (If I changed the code to combine with ctrl instead of cmd, the main function is fired when 'v' is pressed 3 times after ctrl pressed (and not released) and 'v' is shown correctly)
Windows 10 and Ubuntu 18 - sequence: ctrl / v / ctrl+v
KEY Key.ctrl_l
NAME 'ctrl_l'
KEY 'v'
CHAR v
KEY Key.ctrl_l
NAME 'ctrl_l'
KEY 'v'
CHAR v
Main function is only fired if ctrl key is pressed and 'v' is typed twice. but the char is shown correctly
from pynput.
Hi GlassGruber Thanks
I edited your code so I can use in my script
basiclly I need to break a while loop. with ctrl - q
but the code demo is in a loop I can't run two loop in my script.
Luckliy I figure out to use start instead of join.
and ctrl shift keys are different on windows and mac
So I changed a bit to match all system.
Here is it
import pynput,time
is_quit = False
KeyComb_Quit = [
{pynput.keyboard.Key.ctrl, pynput.keyboard.KeyCode(char='q')},
{pynput.keyboard.Key.ctrl_l, pynput.keyboard.KeyCode(char='q')},
{pynput.keyboard.Key.ctrl_r, pynput.keyboard.KeyCode(char='q')}
]
def on_press(key):
global is_quit
if any([key in comb for comb in KeyComb_Quit]):
current.add(key)
if any(all(k in current for k in comb) for comb in KeyComb_Quit):
is_quit = True
def on_release(key):
try:
current.remove(key)
except KeyError:
pass
# The currently active modifiers
current = set()
listener = pynput.keyboard.Listener(on_press=on_press, on_release=on_release)
listener.start()
##### MAIN Script #####
while True:
do something
time.sleep(0.00833)
if is_quit:
break
from pynput.
Sorry, I don't get it how to use join(key) correctly.
I have the listener output "ยดs". How do I turn it into "ล"?
from pynput.
Any progress on implement the key combination feature for this project ?
from pynput.
So I wrote some code & its causing me a headache. I want to have two different combinations. The code I wrote the first combination of keys Ctrl+G or g work but Ctrl + H or h did not but crashes the program. I have re-written my code so many times trying to figure it out that it does not makes sense. Any help? Please help me! I'm really new to python!
Indentation is not working, but if you look at the .txt it is there.
from pynput import keyboard
COMBINATIONS = [
(keyboard.Key.ctrl_l, keyboard.KeyCode(char='g')),
(keyboard.Key.ctrl_l, keyboard.KeyCode(char='G'))]
COMBINATIONS2 = [
(keyboard.Key.ctrl, keyboard.KeyCode(char='h')),
(keyboard.Key.ctrl, keyboard.KeyCode(char='H'))]
#Not working just yet
current = set()
def execute1(): #Function call for character Ctrl G or Ctrl g
print("Detected hotkey")
def execute2(): #Function call for character Ctrl H or Ctrl h
print("Detected 2nd hotkey")
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):
execute1()
if any(all(k in current for k in COMBO) for COMBO in COMBINATIONS2):
execute2()
def on_release(key):
if any([key in COMBO for COMBO in COMBINATIONS]):
current.remove(key)
if any([key in COMBO for COMBO in COMBINATIONS2]):
current.remove(key)
with keyboard.Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
from pynput.
Using the given snippet, dead keys pollute the list and make further comparisons break. For example, when typing in Shift+t, a 'Shift' will be added, then a 'T'. If you then release the Shift, you are left with a 'T', and releasing 't' does not remove it, and the set now will keep containing 'T'.
Is there a way to disable registering dead keys?
As a current solution, I remove the last element in the list when a key is released, ignoring which key it actually is.
from pynput.
See
#182 (comment)
from pynput.
@platelminto, if you run into issues with dead keys, you may want to take a look at #118. The branch fixup-win32-keyboard-listener has a proposed solution.
from pynput.
How do we capture the windows super key events like (windows+r or windows+m etc)
from pynput.
Can you give an example?
from pynput.
Sorry about my last sentence, It's happened due to misunderstanding so I deleted it
from pynput.
@platelminto Had the same problem. I solved it by tracking the shift key down / shift key up movements.
It works also for windows super key events.
from pynput.
from pynput import keyboard from pynput.keyboard import Key from threading import Thread import time COMBINATION = { Key.down, Key.up, Key.left #Key.right } # The key combination to check # 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('All modifiers active!') 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 was looking for a way to detect multiple keypresses at once, and this seemed to be the answer. The only problem is that, for whatever reason, only two keys can be returned at the same time (with occasional exception). How do I detect 3+ keyboard inputs at once?
It seems that pyinput can't handle three or more events at the same time, and where it always replaces the second key with the third. From the looks of it it does this without calling the on_release event.
from pynput.
Related Issues (20)
- Which python version is the latest release of pynput compatible with?
- Keyboardtracking CTRL + "second_key" doesn't output "second_key"
- pynput not detecting media keys on kde plasma wayland HOT 1
- Type method crashes on cyrillic characters HOT 1
- Suppress mouse move not working when using parsec HOT 1
- mouse listener example for win32_event_filter HOT 1
- Script Continues Rapid Clicking Despite Mouse Button Release (is_pressed Functionality Issue) HOT 6
- Press cmd_r and release with cmd pressed will produce two presses instead of press + release HOT 3
- Can this be used in Micropython? HOT 5
- Get the original pressed key HOT 1
- The Numpad numbers does not work in HotKeys.
- pynput types ">" instead of "|" HOT 1
- Need to sync keyboard lock keys
- AttributeError: record_create_context HOT 5
- capslock crshed on macOS HOT 2
- lazy imports cause a KeyError HOT 4
- Cannot install on linux Ubuntu (depends on pywin32) HOT 2
- name 'keyboard' is not defined HOT 1
- Additional keys can still trigger events HOT 2
- Missing 1.7.7 tarball on PyPI
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pynput.