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(", "))
Related
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.
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!
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.
Right now I'm trying to make a small code with a raspberry pi and and a makey makey. The makey makey is a small board that acts as a usb keyboard when certain contacts are powered. My question is what is the easiest way to detect those keypresses inside a python script. I understand using the GPIO pins would be easier, but right now I'm looking for this. I have seen examples such as using using getch() from msvcrt (which from what I understand is windows only,) using pygame.key, and using getKey. Which of theses is easiest to use? Are there any that can detect a key being pressed and a key being released?
Pseudo code:
import whatever needs importing
if the "W" key is pressed:
print ("You pressed W")
elif the "S" is pressed:
print ("You pressed S")
and so on. Thanks.
This is a simple loop that will put stdin in raw mode (disabling buffering so you don't have to press enter) to get single characters. You should do something smarter (like a with statement to disable it) but you get the idea here:
import tty
import sys
import termios
orig_settings = termios.tcgetattr(sys.stdin)
tty.setcbreak(sys.stdin)
x = 0
while x != chr(27): # ESC
x=sys.stdin.read(1)[0]
print("You pressed", x)
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, orig_settings)
I think you'd have to loop to detect key releases in Python.
ETA some more explanation:
On Linux, input to your program will be line buffered. This means that the operating system will buffer up input until it has a whole line, so your program won't even see anything the user typed until the user also hits 'enter'. In other words, if your program is expecting the user to type 'w' and the user does this, 'w' will be sitting in the OS's buffer until the user hits 'enter'. At this point the entire line is delivered to your program so you will get the string "w\n" as the user's input.
You can disable this by putting the tty in raw mode. You do this with the Python function tty.setcbreak which will make a call down the tty driver in linux to tell it to stop buffering. I passed it the sys.stdin argument to tell it which stream I wanted to turn buffering off for1. So after the tty.setcbreak call, the loop above will give you output for every key the user presses.
A complication, though, is that once your program exits, the tty is still in raw mode. You'll generally find this unsatisfying since you don't get any of the power that modern terminal settings offer (like when you use control or escape sequences). For example, notice that you might have trouble exiting the program with ctrl-C. Consequently you should put the terminal back into cooked mode once you are done reading input characters. The termios.tcsetattr call simply says "put the terminal back the way I found it". It knows how to do this by first calling termios.tcgetattr at the beginning of the program which is saying "tell me all the current settings for the terminal".
Once you understand all that, you should easily be able to encapsulate the functionality in a function that suits your program.
1 stdin is the stream that input comes to you from the user. Wikipedia can tell you more about standard streams.
Using a good lightweight module curtsies you could do something like this (taken from their examples/ directory):
from curtsies import Input
def main():
with Input(keynames='curses') as input_generator:
for e in input_generator:
print(repr(e))
if __name__ == '__main__':
main()
So pressing keys on your keyboard gives you something like this:
'a'
's'
'KEY_F(1)'
'KEY_F(2)'
'KEY_F(3)'
'KEY_F(4)'
'KEY_F(5)'
'KEY_LEFT'
'KEY_DOWN'
'KEY_UP'
'KEY_RIGHT'
'KEY_NPAGE'
'\n'
curtsies is used by bpython as a low level abstraction of terminal-related stuff.
The basic problem of decoding the input is that in different terminals and terminal emulator programs like xterm or gnome-terminals physically same keys produce different keycode sequences. That's why one needs to know which terminal settings should be used to decode input. Such a module helps to abstract from those gory details.
Since your question states that you are using a Raspberry Pi and a USB HID keyboard peripheral, but does not specify whether or not you have the Pi configured to boot into text or graphical mode where you will be running your script, I would suggest using libinput which will work in either case.
You can use libinput's python bindings to read keyboard (and most other input devices) events directly from the kernel.
pip3 install python-libinput
The interface to this subsystem is exposed through the character devices which usually live in /dev/input/. They are managed by udev rules which create one or more character devices per attached input device, and are added and removed dynamically when, for example, a USB keyboard is attached or unplugged, or a Bluetooth mouse connects or disconnects.
Libinput handles for you the task of opening and reading from all attached input devices, and opening and closing devices when they are added and removed, respectively.
Using libinput from python to read key events would look like this:
import libinput
def read_key_events():
# init libinput
li = libinput.LibInput(udev=True)
li.udev_assign_seat('seat0')
# loop which reads events
for event in li.get_event():
# test the event.type to filter out only keyboard events
if event.type == libinput.constant.Event.KEYBOARD_KEY:
# get the details of the keyboard event
kbev = event.get_keyboard_event()
kcode = kbev.get_key() # constants in libinput.define.Key.KEY_xxx
kstate = kbev.get_key_state() # constants libinput.constant.KeyState.PRESSED or .RELEASED
# your key handling will look something like this...
if kstate == libinput.constant.KeyState.PRESSED:
print(f"Key {kcode} pressed")
elif kstate == libinput.constant.KeyState.RELEASED:
if kbev.get_key() == libinput.define.Key.KEY_ENTER:
print("Enter key released")
elif kcode == libinput.define.Key.KEY_SPACE:
print("Space bar released")
else:
print(f"Key {kcode} released")
One minor gotcha to be aware of is that udev is commonly configured to set permissions on the event devices it creates in /dev/input/ to allow access only from users who are members of a special supplementary 'input' group, since to allow unrestricted access to raw user key and mouse input would be a major security flaw. As such, o if running this throws an error during the libinput initialisation, you may need to add input to your user's supplementary groups by running:
sudo usermod -G input -a "${USERNAME}"
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