How to get the last key pressed in python? - python

First I want to say that I know that there is a solution with curses.
My programm is a while loop that is run every second. Every second I want to get the last key that was or is pressed. So in case you press a key while the loop sleeps I want that the key is saved so I can get the key that was pressed last even when it isnt pressed anymore. I dont want the saved key to be "deleted" after getting it. So when the user pressed the "a" key I want to get it every second until he pressed another key. If a specific key was pressed i want to print text. This text i want to write in a file using the redirection of stdout:
./test.py > file.txt
My python programm solved with curses looks like this:
import curses
from time import sleep
stdscr=curses.initscr()
stdscr.nodelay(1)
curses.noecho()
curses.cbreak()
while True:
char=stdscr.getch()
if char == 111: #111 = "o" key
print("test")
break
elif char == 97 #97 = "a" key
#code that have to be run every second
#if the a key is the last pressed key!
sleep(1)
curses.nocbreak()
curses.echo()
curses.endwin()
The problem obout this solution is that curses gives me crazy output. I only press one time the "o" key and after the programm stopped file.txt looks like this:
^[[?1049h^[[1;30r^[(B^[[m^[[4l^[[?7h^[[H^[[2Jtest
^[[30;1H^[[?1049l^M^[[?1l^[>
But it should look like this:
test
I would be very greatful if someone writes an answer. I know that python isnt the best choice for programms using keypress events. But i have reasons why i use python for this.
Thank you very much in advance for your answers.

You can install and use the getch package.
import getch
from time import sleep
while True:
char = getch.getch()
if char == 111:
print("test")
break
sleep(1)
(you might need to use getch.getche instead of getch.getch. It's not completely clear from your question)

Related

How do I stop a while loop when a key is pressed with Autokey?

I'm trying to write a small script with Autokey (not regular Python) on Linux Mint which presses a single key and stops after I press another specific key but I can't get it to stop the loop after I press this specific key.
I got the loop working but I can't make it stop.
import time
a = True
b = keyboard.press_key('s')
keyboard.release_key('s')
while a:
keyboard.send_key("a", repeat=5)
time.sleep(2)
if b:
break
So this outputs the letter "a" indefinitely and after I press "s" it doesn't stop and I don't know what I'm doing wrong
I read about the while function and break but all the examples I found were with a loop stopping after it reached a certain number and these examples with numbers are different than what I try to achieve with this kind of script so I hope someone can help me to figure this out.
You will have to use the keyboard module for this, because press_key is used to "press" the keys not to detect.
If you haven't already installed keyboard you can do it by going to cmd,
pip install keyboard
after that you can add the code in python as follows, pressing "q" will print "a" 5 times and pressing "s" will stop the program.
import keyboard
while True:
if keyboard.is_pressed('q'): # pressing q will print a 5 times
for i in range(5):
print("a")
break
elif keyboard.is_pressed('s'): # pressing s will stop the program
break
You can check if a key is pressed with evdev
Check your InputDevice by looking at python -m evdev.evtest
Then to check if the s key is pressed :
import evdev
from evdev import ecodes as e
device = evdev.InputDevice('/dev/input/event7')
if e.KEY_S in device.active_keys():
do_something()
At first glance your problem is that you never update the value of b and it is only assigned before the loop. You should probably try something like this:
import time
a = True
keyboard.release_key('s')
while a:
keyboard.send_key("a", repeat=5)
b = keyboard.press_key('s')
time.sleep(2)
if b:
break
I don't know how "b = keyboard.press_key('s')" affects the code, if it stops it.

How do i fix "break" command doesn't work using keyboard and time input in python?

import keyboard, time
print('You can use :smile: on discord if you want to use emojis.')
write = input('Enter the text you want to autotype:')
def typeman():
time.sleep(1)
keyboard.write(write)
keyboard.press_and_release('enter')
while True:
if keyboard.is_pressed("w"):
while True:
if keyboard.is_pressed("s"):
break
typeman()
This code used to work a couple of months ago, when I press W it types write variable automatically, when I press S it's supposed to stop, but it doesn't work anymore. how to I fix this, and when it used to work I had to hold S for a while for it to stop, how do I break easier?
The nested loops you created were unneeded, using an if and while statement does the trick just fine!
import keyboard, time
print('You can use :smile: on discord if you want to use emojis.')
write = input('Enter the text you want to autotype:')
def typeman():
keyboard.write(write)
keyboard.press_and_release('enter')
while True:
if keyboard.is_pressed("w"): # Check whether to start or not
while not keyboard.is_pressed("s"): # While s isnt pressed
typeman()
time.sleep(1)
# To end that while

Adding reading some character in while loop

I am reading serial data in while loop, I want to add something in code that if I press t than something should be print otherwise while loop should work. I tried to use readchar, but it wait for me to press some key, I dont want it to wait. I want while loop to work till I press some key
Raspberry pi 2.7
while True:
data = s.recv(xxx)
print(data)
if (x == t)
print(Hello)
else:
continue
it is waiting if i use read char.
There are lots of questions already asked on similar topics which would solve your problem. Some of them include the following:
Loubo's "detect key press in python" here on SO, as well as Spae's "Python key press, detect (in terminal, no enter or pause)".
You could use:
import keyboard as kb
num = 0
while True:
if kb.is_pressed('t'):
num += 1
print (num)
Besides that, you have grammar and indentation errors.
Please consult this post on the SO Meta so further problems like this do not occur.

Is it possible to control OMXplayer based on time in Python?

I am trying to control OMXplayer during playback of a video using a Python script. I am new to Dbus on Python, and am hopefully just missing something simple.
Eventually I want to do this with a motion sensor using the GPIO pins, but first I am just trying to get control over the player. What I need to do is loop a section of the video once a certain time passes, and then jump forward to the 'second' section when the passage is interrupted. I am testing this using a key entry.
My problem is that the 'if' statement within the code does not loop unless there is an interruption from a key being inputted, or any other signal. Any key will cause an interruption, but I want the time-specific 'if' statement in the loop to trigger without any input being entered. I hope what I am saying is clear in the below code, but if not please ask any question and I'll be happy to try to clarify.
I am using Will Price's OMXplayer wrapper: https://github.com/willprice/python-omxplayer-wrapper/
My hardware is a Raspberry Pi 3B+
I have looked at similar questions including those below, but have not found the answer:
How to open and close omxplayer (Python/Raspberry Pi) while playing video?
https://www.raspberrypi.org/forums/viewtopic.php?p=533160
I have cleaned out unnecessary parts of the code so this is a basic functioning version.
from omxplayer.player import OMXPlayer #runs from the popcornmix omxplayer wrapper at https://github.com/popcornmix/omxplayerhttps://github.com/popcornmix/omxplayer and https://python-omxplayer-wrapper.readthedocs.io/en/latest/)
from pathlib import Path
import time
import RPi.GPIO as GPIO #for taking signal from GPIO
import subprocess
import logging
logging.basicConfig(level=logging.INFO)
VIDEO_PATH = Path("VIDEO.m4v")
player_log = logging.getLogger("Player 1")
player = OMXPlayer(VIDEO_PATH, dbus_name='org.mpris.MediaPlayer2.omxplayer1')
player.playEvent += lambda _: player_log.info("Play")
player.pauseEvent += lambda _: player_log.info("Pause")
player.stopEvent += lambda _: player_log.info("Stop")
positionEvent = 12
flyin = 3
flyaway = 15
'''
THE ERROR OCCURS IN THE BELOW FUNCTION!!!
the following function does not run each time
the 'while' loop below is playing, but does run
when there is a key pressed as an 'input'
I want to add a chck so that each time a certain
amount of time passes, the video jumps back
'''
def checktime():
currtime = player.position()
print("current time is " + str(currtime))
if(currtime > 3):
print("currtime is greater than 3")
try:
player.play()
print (" Ready")
while True:
'''
Below is the call for the function 'checktime'
This runs once when the video starts, and only
runs again when a key is entered.
I want this to run on a continuous loop
and call each time the video loops
'''
checktime()
key = input()
if key == 'd': #works perfectly
currtime = player.position()
player.seek(flyin-currtime)
print("player position is" + str(player.position()))
if key == 'a': #works perfectly
currtime = player.position()
player.seek(flyaway-currtime)
if key == 's': #works perfectly
player.play()
'''
in addition to the key inputs above, entering any key
and pressing return will run the checktime()
function. I understand that this is receiving an
input, therefore 'waking' the program up,
but I don't understand why the loop is not working
continuously
'''
# Wait for 10 milliseconds
time.sleep(.01)
except KeyboardInterrupt:
print (" Quit")
# Reset GPIO settings
GPIO.cleanup()
The video is controlled using the 's', 'a' and 'd' keys as inputs, and this works perfectly. However, the 'checktime()' function does not call each time the while loop goes around. My guess is that this is because once the video is playing, it is not looking for anything from the Python program until it receives another input.
I am not sure if I am using DBus correctly. Ideally, I wanted to use the seek_absolute function of omxplayer-wrapper, but I haven't been able to understand this. I have been ploughing ahead on this project and have gotten a better understanding since posting an earlier question (see here: OMXplayer-wrapper and Python - jump to a specific point in video) but I am a bit stumped here.
If anyone can help I would appreciate any suggestions!

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!

Categories

Resources