I'm trying to do something that seems very basic, but I keep getting myself stuck inside of loops that don't allow me to perform other actions. For example:
def functionOne():
if x key is pressed:
do something
def functionTwo():
if y key is pressed:
do something else
def functionThree():
if z key is pressed:
do something else
def main():
functionOne()
functionTwo()
functionThree()
main()
I was trying to to do while loops in each function, but that locks each function in its own loop cycle. I essentially want my program to run until I press a very specific key combination from the Python keyboard package. I assume loops are the way to keep a program running?
Or say, if I wanted to implement this on a GUI, and only exit the program when hitting the quit button on the GUI, while waiting for the other buttons to be clicked to do something else.
I'm aware that I could do a giant main loop with conditions nested inside one another, but I'm hoping there is a cleaner way to do this involving functions.
Try this way:-
def functionOne(key):
if key != 'x':
return
if x key is pressed:
do something
def functionTwo(key):
if key != 'y':
return
if y key is pressed:
do something else
def functionThree(key):
if key != 'z':
return
if z key is pressed:
do something else
def main():
while key != 'q':
key = input("Enter the key :")
functionOne(key)
functionTwo(key)
functionThree(key)
main()
Other than that you can use threading if functions are computationally heavy and key input interval is smaller than the computational time of the functions.
you could take advantage of pynput
first install it
pip install pynput
then you can achieve what you are looking for like the following example (obtained from pynput documentation):
from pynput import keyboard
def on_press(key):
try:
print('alphanumeric key {0} pressed'.format(key.char))
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
# Collect events until released
with keyboard.Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
# ...or, in a non-blocking fashion:
listener = keyboard.Listener(
on_press=on_press,
on_release=on_release)
listener.start()
Related
I am making a program in python to detect what key is pressed and based on my keyboard it will make a decision.
I want to implement it using keyboard module in python.
I would do something like this,
import keyboard
while True:
if keyboard.read_key() == 'enter':
print('Enter is pressed)
if keyboard.read_key() == 'q':
print('Quitting the program)
break
if keyboard.read_key() == 's':
print('Skiping the things')
But it doesn't work. When I execute this program, I have to press s twice to execute the "s" block.
Also, I have a problem that is after the execution is finished, it writes all the keys in my command prompt is it possible to fix that?
As per Keyboard documentation:
Other applications, such as some games, may register hooks that swallow all key events. In this case keyboard will be unable to report events.
One way to solve your problem with keyboard module is keyboard.wait('key')
# Blocks until you press esc
keyboard.wait('esc')
Something work around is as below:
import keyboard
keyboard.wait('enter')
print('Enter is pressed')
keyboard.wait('q')
print('Quitting the program')
keyboard.wait('s')
print('Skiping the things')
As Far I Know There is only one efficient way to Detect user input weather it keybored or mouse input Which is library called pynput ......
from pynput.keyboard import Key , Listener , Controller
keyboard = Controller()
DoubleShot=False
shot=False
def on_press(key):
global DoubleShot
global shot
if Key.num_lock == key:
print("activate")
DoubleShot=True
if DoubleShot:
if Key.shift == key:
shot = not shot
if shot:
keyboard.press(Key.shift)
keyboard.release(Key.shift)
def on_release(key):
if key == Key.esc:
return False
with Listener(on_press=on_press , on_release=on_release) as listener:
listener.join()
i create this for a game to shoot multiple time on 'shift' clicked
code activate only when ' numlock ' clicked.....
Controller is for clicking any key you want
Note:
In My case infinity looping was a problem that's why shot variable is there to stop looping
I just found out about the pynput library which is exactly what I have been looking for. My goal is to capure the keys the user is typing and whenever a specific sequence of keys was captured I want the computer to write a sequence to the current carret's position. After that I want to capture the usersĀ“s keys again until another noteworthy sequence occurs. And so on.
The problem is that the simulated key strokes of keyboard.write() are also considered by the Listener which leads to an infinite loop which was funny the first time it occurred but I am trying to get rid of it now obv.
My approach is to stop the Listener and create a new one after the computer is done typing but this process slows down a lot after the first start_listener() invocation and isn't optimal in the first place I think. And I am out of further ideas so I was hoping someone could help here.
Here is my code so far:
import keyboard
from pynput.keyboard import Key, Listener
def on_press(key):
stop_listener()
keyboard.write("Hello", 0.05)
start_listener()
def on_release(key):
if key == Key.esc:
return False
def start_listener():
global listener
listener = Listener(on_press=on_press, on_release=on_release)
listener.start()
listener.join()
def stop_listener():
global listener
listener.stop()
with Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
There is a simple solution to the problem. I actually missed that I used two packages that have nothing to do with each other. Thanks to the ease to install them on my IDE.
Anyway my solution is now to only use the already present keyboard package https://pypi.org/project/keyboard/ and not pynput.keyboard
It turn out to be really easy when not using two separate packages :).
Here is the code:
# coding=utf8
import keyboard as k
def on_press(key = k.KeyboardEvent):
k.write(key.name, 0.0)
k.on_press(on_press)
k.wait()
On my Linux Mint I need admin privileges to run keyboard but I can do the same with pynput.keyboard.Controller and methods press(), release(), time.sleep()
Instead of stoping and starting listenere I would use global variable paused = False to control when on_press should runs code.
from pynput.keyboard import Key, Listener, Controller
import time
keyboard = Controller()
def on_press(key):
global paused # inform function to assign new value to global variable (instead of creating local variable)
if not paused:
paused = True
#keyboard.type("Hello") # module pynput.keyboard.Controller
for char in "Hello":
keyboard.press(char) # pynput.keyboard.Controller
keyboard.release(char) # pynput.keyboard.Controller
time.sleep(0.05)
paused = False
def on_release(key):
if not paused:
if key == Key.esc:
return False
# global variable with default value at start
paused = False
with Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
Tested on Linux Mint 20, Python 3.8.5, pynput 1.7.3
I have a Python module that listens for a key combination using pynput then, once it's pressed, it types a string into a text program.
It works great! Except...
In the example below, the user's key combo is set to shift + space. This makes a lot of sense and will likely be the most common chosen key command for Windows users running my program. The trouble is, while the shift key is held down it changes what pynput types. Instead of 01/20/2019, it will type )!/20/2019.
I need a way to disable the keyboard until pyautogui is finished typing the string. Thanks a lot for your help!!!
Bonus question: I can't seem to get a result when the key combination includes a ctrl key. Key.ctrl simply fails to ever trigger, whilst other keys work fine.
from pynput.keyboard import Key, Controller, Listener
import time
keyboard = Controller()
def insert(): # check line 1 of config file
keyboard.type('01/20/2019')
# 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): # I don't know what this k in current for k shit is.
current.remove(key)
insert() # run insert
if key == Key.esc:
listener.stop()
def on_release(key):
try:
current.remove(key)
except KeyError:
pass
with Listener(on_press=on_press, on_release=on_release) as listener:
listener.join()
``
You can use pyautogui.keyUp("shift") before you type.
def insert():
f=open('tc.txt')
line=f.readlines()
insert.timestamp=(line[0])
time.sleep(.1)
pyautogui.keyUp("shift")
pyautogui.typewrite(insert.timestamp)
I'm trying to make a program that outputs a key press event as a response to another keyboard event. How do I get it to use the particular value of the key pressed in a conditional statement? The codes I try seem to be skipping the conditional statement altogether.
Initially tried [if key == '1':], then tired by [if key == 1:]. Also tried various means of assigning [key] to a variable. Also tried [print('2')] instead of using [pyautogui.typewrite('2')]. Tried putting the code both in on_press(key) and in on_release(key).
`
import pyautogui
from pynput.keyboard import Key, Listener
def on_press(key):
print('{0} pressed'.format(key))
def on_release(key):
print('{0} release'.format(key))
k = format(key)
if k == '1': #THIS IS THE PART I CAN'T GET TO WORK
pyautogui.typewrite('2', 0.5)
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()
`
Expected to output '2' whenever I press '1' on the keyboard(in addition to the output of the keypress and keyrelease event). The output for the pressing of '1' doesn't work.
You can use keyboard library, in order to handle/create key events.
while True:
try:
if keyboard.is_pressed('1'):
print('{} is pressed'.format(1))
break
else:
pass
except:
break
the above code runs until 1 is received as a keypress. Upon pressing the key, 1 is pressed will be printed.
You can further use other functions of this library, in order to detect a key down even too.
The key parameter that your on_press/on_release receives is not the character string but rather a Key/KeyChar object, that's why you can't compare it directly with a string.
To access the keyboard input character, use key.char instead:
def on_press(key):
print("pressed '{}'".format(key.char))
Look at the example codes on pynput's documentation on how to capture non letter keys.
from time import sleep
alive = True
while alive == True:
print("You have awoken in a unknown land.")
sleep(2)
print("\nDo you go north, south, east or west?")
print("Press the up arrow to go north.")
print("Press the down arrow to go south.")
print("Press the left arrow to go west.")
print("Press the right arrow to go east.")
input(" ")
How do I get the user to press one of the arrow keys and have the program carry on without the need of pressing the enter key?
Thanks in advance!
~Lorenzo
You may look into a package like pynput for multiplatform support. Pynput implements mouse and keyboard listeners. This will also allow you to do WSAD movement in your RPG-like game.
For keyboard listeners, you can have a onpress/onrelease key. The help files will have some better examples.
from pynput import keyboard
def on_press(key):
try:
print('alphanumeric key {0} pressed'.format(
key.char))
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
# Collect events until released
with keyboard.Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
If you want to use up/down/left/right (arrow keys) for movement, this may be the easiest least painful solution too.
You Could Make Options Like:
option = input('1/2/3/4:')
or:
Python has a keyboard module with many features. You Can Use It In Both Shell and Console.
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('up'): #if key 'up' is pressed.You can use right,left,up,down and others
print('You Pressed A Key!')
#your code to move up here.
break #finishing the loop
else:
pass
except:
break #if user pressed other than the given key the loop will break
You can set it to multiple Key Detection:
if keyboard.is_pressed('up') or keyboard.is_pressed('down') or keyboard.is_pressed('left') or keyboard.is_pressed('right'):
#then do this
You Can Also Do Something like:
if keyboard.is_pressed('up') and keyboard.is_pressed('down'):
#then do this
It Also Detect Key For The Whole Windows.
Thanks.