I my python module keyboard commands are working fine as long as I don't have anything else in the infinite while loop.
As soon as I have something else in the while loop, the keyboard.is_pressed() does not work.
Can anyone explain why?
import keyboard
import time
while True:
if keyboard.is_pressed('a'):
print("/t/tThe 'a' key has been pressed")
time.sleep(0.1)
if keyboard.is_pressed('b'):
print("/t/tThe 'b' key has been pressed")
time.sleep(0.1)
if keyboard.is_pressed('q'):
print("/t/tThe 'q' key has been pressed")
break
for k in range(0,11,1):
print('k is at ' + str(k))
time.sleep(0.1)
print('DONE')
Ok. I got it. The problem is that the while loop runs very fast. So to explain the problem the thing is that when in any iteration of while loop your if statements will be processed with very fast speed but in your for loop you are printing 10 values with 0.1 sleep time each and hence spending 1 second in the for a loop. So for you to get the result of pressing key 'a' you have to press it in the very very split second when your for loops end and while loop starts which is not possible and hence the only solution is that you remove the for loop.
is_pressed() returns true only if the key is depressed right now.
If you press and release the key at normal speed, it's unlikely that it will be depressed during the few milliseconds when is_pressed() is called.
Related
This question already has answers here:
How to detect key presses?
(17 answers)
Closed last year.
I have a simple question for you, which I dont seem to find an answer too.
Im trying to make an AutoClicker of sort, to press a keyboard key continuesly.
Here is my code:
while True:
keyboard.wait(k) ## k = k to press
mouse.click('left') ## the click
time.sleep(0.5) ## delay
This code works fine, but I have a problem, if I press an another key with 'K' it doesnt work, and I want to make it click anytime there is the 'K' key pressed, no matter with what other key it is pressed with. Like if I press K + B + C I want the autoclicker to still activate because K is pressed. I have tried searching for a solution to this problem but I havent found anything.
Thanks for any help!
It looks like the below question solves your issue. I tried it and it works for the combination of K + B + C key presses. You need to install keyboard module.
How to detect key presses?
Code that I tried (copied from the question above with minor updates)
import time
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('k'): # if key 'q' is pressed
print('You Pressed k Key!')
#break # finishing the loop
except:
break # if user pressed a key other than the given key the loop will break
time.sleep(0.1)
Note: Without the sleep of 0.1, the key press event is printed multiple times.
I was hoping someone could help me with this issue. I'm hoping it's fairly simple to fix, but I have been trying for a while to figure this out. I have trimmed my larger code to this, as I believe the issue here is the crux of the problem.
I have a raspberry pi and an external button. This is on python3 on Linux. I am using GPIOZero for the button. The code below I believe is simple to understand, but basically, I want a function to loop at all times. When I press a button I want another function to run, but only if a variable is a certain number. I describe what I ultimately want to happen in a comment below, but my code is unfinished and simplified just for this problem.
I only want button.when_pressed to work when timer = 0. The problem is, once the code naturally gets into the button.when_pressed function, it never "lets go" of the function again. When I successfully redefine the variable to timer = 1, it still prints button is pressed when I press the button. I don't know why. To me, it seems like it should only work once timer = 0.
Any suggestions? I think I have a misunderstanding of global variables I will plan on researching. I'm not sure if that's the issue. I have also tried using break and continue to try to get it "back on its loop" but that hasn't worked either. Also I want to use button.when_pressed instead of btn.is_pressed, because I want the program to only do something when I'm holding the button down once, and not loop when I'm holding it down. In this case, I want button is pressed to print a single time. If I did btn.is_pressed it would print button is pressed every two seconds, which I dont want.
Thanks for any help. I'm happy to learn.
#!/usr/bin/python3
from gpiozero import Button
from time import sleep
import time
button = Button(4)
timer = 0
def press():
print("Button is pressed")
global timer
timer = 1
def loop():
global timer
timer = 1
while True:
if timer == 0:
button.when_pressed = press
else:
loop()
sleep(2)
If you want to disable the callback you had set to button.when_pressed, you need to do another assignment with button.when_pressed = None. This is listed in the documentation:
when_released:
[...] Set this property to None (the default) to disable the event.
It's not exactly clear what behavior you want from your current code. If you want the button to be active for 2 seconds, then be deactivated indefinitely, you can use:
button.when_pressed = press
sleep(2)
button.when_pressed = None
There's no need for a loop, since you don't want to repeat anything.
If you only want the button to be active for a single button press, that needs to happen within 2 seconds, you could instead call button.wait_for_press(2). I hesitate to write a full block of code for that though, as the docs don't specify how a timeout is signaled (it might be by return value, or via an exception). I don't have a Raspberry Pi so I can't test myself, but you could try it out and see what happens.
Treat your whole piece of code as one "black box", ask yourself, what is the input/output? button press or timer mode? (because I don't quite understand what does timer variable mean in your code)
Your code implies timer mode is the top level input to control the flow,
while True:
if timer == 0:
button.when_pressed = press
else:
loop()
sleep(2)
Is it expected?
If you allow user to press the button at any time, suggest you make button press to be your top level input, change the logic to keep when_pressed callback always on, set flag once triggered, and then check if the button has been pressed and still is_pressed in your while loop.
pressed = False
def play_video_1():
pass
def play_video_2():
pass
def press():
print("Button is pressed")
global pressed
pressed = True
button.when_pressed = press
while True:
if pressed and not_playing_video2:
if is_pressed:
play_video_1()
else:
pressed = False
play_video_2()
else:
play_video_2()
for now I'm just trying to get it to work with the keyboard spammer. So far I have done much searching but nothing seems to work.
if you have any tips on how to make the spamming stop without having to close the application it would be appreciated.
This is the code:
from typing import KeysView
import keyboard
import time
keyboard.wait("esc")
x = 4
while x != 5:
for i in range(9):
time.sleep(0.4)
print(keyboard.send("ctrl+v,enter"))
time.sleep(6)
(thanks)
Using the keyboard module there are many ways you could do this, one of them would be to add a hotkey that stops your loop via a global variable (in this example it's when you hit the spacebar):
from typing import KeysView
import keyboard
import time
keyboard.wait("esc")
running = True
def on_space():
global running
running = False
keyboard.add_hotkey('space', on_space)
while running:
for i in range(9):
time.sleep(0.4)
print(keyboard.send("ctrl+v,enter"))
time.sleep(6)
Adding a check for if a key is pressed inside of the for loop should do the trick. You could either make pressing the key break the loop, or since your loop waits for x to equal 5, you could simply make pressing the key change x to 5.
I'm attempting to use the python library pysdl2 to construct an emulator. The library has been working well so far, however I've been having problems receiving keyboard input.
What I essentially needed to do is test if certain keys are pressed. After doing a bit of research, I discovered sdl2.SDL_GetKeyboardState which supposedly is the same SDL function as SDL_GetKeyboardState. Following the previously linked documentation and this article on the Lazy Foo' Productions website, I constructed the following script:
import sdl2
sdl2.ext.init()
window = sdl2.ext.Window('Test', size=(640, 480))
window.show()
key_states = sdl2.SDL_GetKeyboardState(None)
running = True
while running:
for event in sdl2.ext.get_events():
if event.type == sdl2.SDL_QUIT:
running = False
break
if key_states[sdl2.SDL_SCANCODE_A]:
print('A key pressed')
window.refresh()
The above code is suppose to detect if the a key is pressed and if so print a message out. When the above program is run, a window does appear, but when the a key is pressed, 'A key pressed' is printed over four thousand times. It does not continue to print the message, it only prints it once thousands of times, then stops.
At first, I consider that the problem may have been that the key deduction code (lines 15-16) should be inside of the the event loop (lines 11-14). It worked to some degree. Rather than 'A key pressed' being printed out thousands of times per key press, it was only being printed out twice per key press.
Is there a problem with my code? Am I missing something about how to correctly use the sdl2.SDL_GetKeyboardState function? How can I properly detect key presses?
Sounds like it's working the way it's supposed to. key_states[sdl2.SDL_SCANCODE_A] will return true whenever a is pressed. And there's not much processing going on in your loop, so it'll loop as fast as your CPU allows, printing out "A key pressed" hundreds or thousands of times per second, until you release the key.
You could check for a different event type, such as SDL_KEYDOWN, which operates more like how you're wanting, or you can keep track of the keypress with a variable, for example:
key_down = False
while running:
for event in sdl2.ext.get_events():
if event.type == sdl2.SDL_QUIT:
running = False
break
if key_states[sdl2.SDL_SCANCODE_A] and not key_down:
print('A key pressed')
key_down = True
elif not key_states[sdl2.SDL_SCANCODE_A] and key_down:
print('A key released')
key_down = False
window.refresh()
I want to break an infinite loop when pressing space bar. I dont want to use Pygame, since it will produce a window.
How can i do it?
I got an answer. We can use msvcrt.kbhit() to detect a keypress. Here is the code i wrote.
import msvcrt
while 1:
print 'Testing..'
if msvcrt.kbhit():
if ord(msvcrt.getch()) == 32:
break
32 is the number for space. 27 for esc. like this we can choose any keys.
Important Note: This will not work in IDLE. Use terminal.
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(' '): #if key space is pressed.You can also use right,left,up,down and others like a,b,c,etc.
print('You Pressed A Key!')
break #finishing the loop
except:
pass
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'): #if both keys are pressed at the same time.
#then do this
Hope This Helps You.
Thanks.
Using space will be difficult because each system maps it differently. If you are okay with enter, this code will do the trick:
import sys, select, os
i = 0
while True:
os.system('cls' if os.name == 'nt' else 'clear')
print ("I'm doing stuff. Press Enter to stop me!")
print (i)
if sys.stdin in select.select([sys.stdin], [], [], 0)[0]:
line = input()
break
i += 1
Source