Why pynput doesn't detect numeric keyboard presses? - python

I'm using python 3.7 on windows 7.
Is there any way to detect number (for example: "1") key presses in pynput module?
I have tried many other modules and i got nothing except for tkinter
which needs a window but i don't want that.
from pynput import keyboard
def on_press(key):
print(key)
if str(format(key)) == 'Key.1':
print('Exiting...')
return False
with keyboard.Listener(on_press = on_press) as listener:
listener.join()
It actually only prints the pressed key and never brakes(doesn't accept the numeric input).

Your code is testing for the value "1". This is, your pardon for stating the obvious, what pynput returns if you press the 1 key. You want to respond to the NumLock key.
Instead of
if str(format(key)) == '1':
you can code either of these tests, both of which check for the value you are looking for:
if key == keyboard.Key.num_lock:
if str(format(key)) == "Key.num_lock":
But... There are two kinds of NumLock key.
One is Keyboard NumLock and Clear which has both a USB code (0x53) and a Windows virtual key code (0x90). pynput will respond to pressing this key.
The other kind is Keyboard Locking NumLock which works at the keyboard level: it changes the way your keyboard behaves, and Windows doesn't get to hear about it. It has a USB code (0x83), but it doesn't have a Windows virtual key code. If there is no virtual key code for the key, there won't be a Windows message for pressing it, and pynput reports Windows messages.
So the behaviour is hardware-dependent and it may be that your machine has the second kind of NumLock key. If it does, then nothing you can say to pynput will help. This is unlikely, though, unless you are working with a very restricted laptop keyboard.

The code you've provided seems to be trying to detect Numeral key '1' rather than 'Num lock'.
#BoarGules has provided a complete answer. Just to add a bit of clarification:
When you monitor keyboard using pynput, if trying to detect a control key, you should compare it with appropriate pynput.keyboard.Key object. In case of checking for num lock, your code should look like this:
if key == keyboard.Key.num_lock:
print('exiting')
On the other hand, if you're looking for an alpha-numeric key, compare it with pynput.keyboard.KeyCode:
if key == keyboard.KeyCode(char = '1'):
print('exiting')

A quick glance at the doc shows that the num lock key may be undefined on some platforms. I don't have a windows machine to test this on unfortunately.
num_lock = <Key.f1: 0>
The NumLock key. This may be undefined for some platforms.

Related

Is there a way to detect a key press in a python Replit?

I am making a chat app in Replit through Python. I have a while true loop that checks if a message has been posted and will check if you pressed the T key, and if so, pauses the loop to let you type and send your message. Because it is on replit, I cannot give root access.
I have tried using the keyboards module functions, like keyboard.is_pressed('t'), but that requires root access. I have looked through the docs there and have not found anything. I have also tried using the solutions in How to detect key presses?.
I am not familiar with Replit, but, if you're on a Windows machine, you might solve it with :
import msvcrt
while True:
# Check if a message has been posted
# ...
# Check if the 't' key has been pressed
if msvcrt.kbhit():
# Read the character from the keyboard
ch = msvcrt.getch()
if ch == b't':
# Pause the loop and let the user type and send a message
# ...
Not sure if it helps for your usecase, maybe for others. cheers.
I used the getKey Module for it:
from getkey import getkey
key = getkey()
if key == 't':

Python pyautogui Windows 10 control shift end combo fails

I am writing some code to copy data from an Excel file, but I cannot get it to work.
Any help would be greatly appreciated.
Code used below that did not work:
pyautogui.hotkey('ctrl', 'shift', 'end')
or
pyautogui.press('ctrl')
pyautogui.press('shift')
pyautogui.press('end')
pyautogui.release('ctrl')
pyautogui.release('shift')
pyautogui.release('end')
also
pyautogui.keyDown('ctrl')
pyautogui.keyDown('shift')
pyautogui.keyDown('end')
pyautogui.keyUp('ctrl')
pyautogui.keyUp('shift')
pyautogui.keyUp('end')
On Windows, you need the number lock off.
With the number lock on, pyautogui seems to choose "end" from the 1-numpad instead of the "end" key. But with the number lock off, it highlights to the end in Notepad or Notepad++.
This seems like an ambiguity pyautogui should be resolving, but it is a tricky case.
If you want to check if the number lock is on before sending pyautogui.press('numlock'), see this question: Python 3.x - Getting the state of caps-lock/num-lock/scroll-lock on Windows
Below line worked fine
pyautogui.hotkey('ctrl','shiftright','shiftleft','end')
Use "ctypes library" to check the keyboard's numlock key state and either disable it or switch hotkeys accordingly.
Getting numlock key state code:
# ctypes accesses C functions through Python, interfacing with platform libs.
import ctypes
def is_numlock_on():
"""
Use the GetKeyState function from the user32 DLL to check the state of the numlock key.
A virtual-key code is a unique value assigned to each key by the operating system.
The virtual-key code for numlock key is 0x90.
"""
return True if ctypes.windll.user32.GetKeyState(0x90) & 1 else False
After this, you can press numlock key to disable it depending on its current state but I suggest you be independent of numlock.
So, instead, you should use conditional hotkeys based on the current state of numlock:
COND_HOTKEY = "ctrl, shiftright, shiftleft, end" if is_numlock_on() else "ctrl, shift, end"
pyautogui.hotkey(*COND_HOTKEY.split(", "))

Detect key release while using keyboard module

Warning: my English sucks and also I'm really new to python
So I'm making a program that requires a specific Key Press (e.g. space bar) to continue the loop, like:
for i in *some sort of list*:
print(something)
*waits for a key*
and my method for the last line is the keyboard module (not from pynput), which has the functionis_pressed. When I pressed a key, I got the output:
*something*
*something*
*something*
*repeats for several times*
I know that the function detects key press instead of press and release, so this output stops as soon as I release it. But that not how my program works. It should respond every time I release that key. Unfortunately I couldn't find a function called is_released or something, and module pynput can't get the key I pressed using Listener. At least I can't.
Also, is there a way to have both keyboard and pynput importable in a computer? My VS Code ignores keyboard when pynput is installed.
Edit: this is my solution for the problem, but it's super dumb:
while True:
if keyboard.is_pressed('space'):
while True:
if not keyboard.is_pressed('space'):
break
break
Is there a function that does the same thing?
Since it detects keypress only, use flags. I think something like this can do it:
1. Make a bool variable to detect a single key press
2. If key is pressed, the bool will be set to true
3. If bool is true and not key.is_pressed: do your thing
4. Set bool to false after operation
For example, in code, that will be like this:
keypress = False
key = 'space'
while True:
if keypress and not keyboard.is_pressed(key):
'''DO YOUR THING'''
#beak out of while loop?
keypress = False
break
elif keyboard.is_pressed(key) and not keypress:
keypress = True
Dont know if this is how you'll do it, but I guess you can get my drift from this. Good luck!

Keypress detection

I've been trying to get keypresses to be detected in a Python program. I want to find a way to do this without using Tkinter, curses, or raw_input. Here's what I'm going at:
while True:
if keypressed==1:
print thekey
Does anyone know how this is possible?
Python has a keyboard module with many features. Install it, perhaps with this command:
pip3 install keyboard
Then use it in code like:
import keyboard #Using module keyboard
while True:#making a loop
try: #used try so that if user pressed other than the given key error will not be shown
if keyboard.is_pressed('a'): #if key 'a' is pressed
print('You Pressed A Key!')
break #finishing the loop
else:
pass
except:
break #if user pressed other than the given key the loop will break
You can set multiple Key Detection:
if keyboard.is_pressed('a') or keyboard.is_pressed('b') or keyboard.is_pressed('c'):
#then do this
I took the liberty of editing your question slightly so it makes sense and has an answer, at least on Windows. (IDLE only interacts with your keyboard by means of the tkinter interface to tk.) On Windows, the answer is to use the msvcrt module's console io functions
import msvcrt as ms
while True:
if ms.kbhit():
print(ms.getch())
For other systems, you will have to find the equivalent system-specific calls. For posix systems, these may be part of curses, which you said you did not to use, but I do not know.
These functions do not work correctly when the program is run is run from IDLE in its default mode. The same may be true for other graphics-mode IDEs.

Detecting Key Presses using win32api in Python

I'm trying to break a loop in Python with a specific key press using win32api. How would one go about this?
What is the actual version of win32api.KeyPress('H'), in the following code?
Revised:
import win32api
while True :
cp = win32api.GetCursorPos()
print cp
if win32api.KeyPress('H') == True :
break
I want to be able to break a loop by pressing the h key.
Edit:
I'm attempting to make a program that repeatedly reports mouse positions and I need a mechanism to exit said program.
See revised code.
win32api is just an interface to the underlying windows low-level library.
See the GetAsyncKeyState Function:
Determines whether a key is up or down at the time the function is called, and whether the key was pressed after a previous call to GetAsyncKeyState.
Syntax
SHORT WINAPI GetAsyncKeyState(
__in int vKey
);
Return Value
Type: SHORT
If the function succeeds, the return value specifies whether the key was pressed since the last call to GetAsyncKeyState, and whether the key is currently up or down. If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState.
Note that the return value is bit-encoded (not a boolean).
To get at vKey values, an application can use the virtual-key code constants in the win32con module.
For example, testing the "CAPS LOCK" key:
>>> import win32api
>>> import win32con
>>> win32con.VK_CAPITAL
20
>>> win32api.GetAsyncKeyState(win32con.VK_CAPITAL)
0
>>> win32api.GetAsyncKeyState(win32con.VK_CAPITAL)
1
The virtual-key constant for simple letters are ASCII codes,
so that testing the state of the "H" key (key was pressed) will look like:
>>> win32api.GetAsyncKeyState(ord('H'))
1
This isn't how it works in GUI programming. You don't call a method to check for a key press. Instead you get sent messages when keys are pressed. Assuming that you have a window that is receiving input then you need to respond to the WM_KEYDOWN message arriving in your window procedure, or message map in Python win32api terms.
Your edit shows that you are not using the message queue which is rather unusual. You may be able to achieve what you wish by calling GetAsyncKeyState().
Check the python tiler on github, very useful even if you are trying to just find key codes to send. Also this will be useful if you are running your code in the background and want to break the loop from outside the window.
git project:
https://github.com/Tzbob/python-windows-tiler
code with windows keys:
https://code.google.com/p/python-windows-tiler/source/browse/pwt/hotkey.py?r=df41af2a42b6304047a5f6f1f2903b601b22eb39

Categories

Resources