Python: display dynamic information on user input - python

I would like to be able to receive command line input from user in a python script, and at the same time display to the user some dynamic information.
The user should be able to enter text, but this should not block the displaying of information.
My goal is to create a game, where I show users a countdown while they still have time to enter an answer.
Is this achievable?

Yeah. To create a countdown in the console, you could do something like this:
from time import sleep
for num in reversed(range(0,11)):
print(num)
sleep(1.0)
or
from time import sleep
time = 10
while time != 0:
print(time)
time = time - 1
sleep(1.0)
Either will countdown from 10 to 0 with a second in between each number. Since you might want the user to be able to enter answers as quickly or slowly as like before reaching 0... you might want to look into running two loops concurrently. this thread might be helpful for that. You'll want to figure out how to break out of both loops if the user gets the right answer (and have something come up that says they got the right answer) or if the user runs out of time.

Well sounded like an interesting thing to look into so I did, ran into a few problems pretty soon.
First, I was able to make a running counter but the problem is, since it is a loop, the next layer the counter loop will reset everything you've answered on the previous layer unless you've pressed enter to input answer(answer + enter , during that 1 second period).
if you are making reflex based thing that you only need to press single keys you might be able to succeed with my code by using module getch.
There were few modules that I could use for making the timer and program run at the same time, threading and multiprocessing(better results with threading).
It's basically a working thing if you just remove the counter function which adds the loop, but you won't see the timer.
Pygame might be a good thing to do this with, haven't used it myself but I'd presume so.
here is my code
import time
import threading
import os
timel = 5
def question():
q = input("",)
print(q)
if q == "2":
print("\nCorrect")
else:
exit("\nFalse, You lose!!")
def counter():
timel = 5
for i in range(0, timel):
print("How much is 1+1?", timel)
timel -= 1
time.sleep(1)
os.system("cls")
def timer(seconds):
time.sleep(seconds)
exit("\nTIMES UP, You lose!!")
def exit(msg):
print(msg)
os._exit(1)
def main():
thread = threading.Thread(target=timer, args=(int("{}".format(timel)),))
thread2 = threading.Thread(target=counter)
thread.start()
thread2.start()
question()
if __name__ == "__main__":
main()

Related

How to use Threading timers in a while loop

What I need help with.
The only reason I used 2 seconds was to delay the messages but I am using a while loop: now since the for loop: did not really work the timer delay does not seem to be working for some reason regardless of what I do. I don't want to use time.sleep() since it would delay the loops in the future I plan to add multiple threads. It seems easy I think the threading module is very bug or at least it does not work the way a person might expect from it but if anyone is experienced with this module it would be a big help. I am sure the answer is simple but I am an idiot that is why I can not figure it out.
from threading import Timer
isint = True
while (isint):
x =input("How many 'somethings' : ")
try:
x =int(x)
isint=False
except ValueError:
print("Type in a number.")
def something():
global x
if x > 0:
print('Something')
x = x-1
else:
pass
while True:
Timer(10 , something).start()
You should use different value for every Timer
Timer(10, ...)
Timer(12, ...)
Timer(14, ...)
And with loop
for i in range(x):
Timer(10 + i*2, something).start()
and every timer will start 2 seconds later after previous timer without using sleep()

Is there a way to cancel an input() in Python 3.8 after a certain period of time? [duplicate]

This question already has answers here:
Keyboard input with timeout?
(28 answers)
Closed 2 years ago.
I'm writing a program in Python 3.8. I'd like to make an input, let's say variable v. If v is input as "n," then some code is run. Any other input does nothing. Additionally, if the time runs out and nothing is inputted for v, then the "n" code is run.
I've tried a couple of different timers which work alright, but I'm struggling on how to cancel the input, since it stops my whole program and won't proceed onto the code I want to run.
Here's what I have:
def timerMethod():
timeout = 10
t = Timer(timeout, print, ['Sorry, times up'])
t.start()
prompt = "You have %d seconds to choose: are you feeling ok? y/n: \n" % timeout
answer = input(prompt)
if (answer == "n"):
feelingBad = True
t.cancel()
The two problems that I've encountered are 1. feelingBad (global variable) will never be made true. I feel like this is a basic Py principle that I've forgotten here, and I can change the way the code is written here, but if you'd like to point out my error please do. The main problem 2. is that if there is no input for the answer variable, the timer will end but the program will not proceed. If someone could please help me on the right track as on how to cancel the input prompt when the timer runs out, I'd greatly appreciate it.
Check the multithreading
here. I wish there was a better explanation on how it works. In my own words, one thread starts and sets the start time which is taken up by the second. Instead of a timer that counts down, it runs an if statement which compares the time taken with the time limit, which gives a space for any code to be run before the program exits.
You can try this:
import time
from threading import Thread
user = None
def timeout():
cpt = 0
while user == None:
time.sleep(1); cpt += 1
if user != None:
return
if cpt == 10:
break
print("Pass")
Thread(target = timeout).start()
user = input()

Python does't run some lines of code as it should

can someone help me with this code? It's use is to make timed input for 2 seconds and it needs to print the last line even if the user did or didn't type something in the console (for that time). When I don't type in anything, after printing "Too Slow" it asks me for the same input, so I added IF, but it doesn't really notice it. I hope that someone can help me. Thanks!
import time
from threading import Thread
i = 0
answer = None
def check():
time.sleep(2)
if answer != None:
return
print("Too Slow") #prints this if nothing is typed in (for 2 seconds)
if i == 0:
i = 1
Thread(target = check).start()
answer = input("Input something: ") #program doesn't even notice IF and asks me the second time for input
print("This should be printed instantly after printing Too Slow (when user doesn't input anything)")
The return in the check function only causes the thread to be completed, but the call to input is independent of that thread and thus not interrupted when the check function completes. See this answer for an alternative solution using the signal module.

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!

How to temporarily disable keyboard input using Python

I'm writing a simple program for Windows using Python, and this program takes advantage of the time module. Specifically, I'm using time.sleep(x) to pause the program for a short moment, generally 0.5-2 seconds. Here's basically what I'm doing:
import time
time.sleep(2)
while True:
x = input(prompt)
if x == 'spam':
break
The problem with this is, if the user presses enter while time.sleep has it paused, then those enters will be counted towards the input in the while loop. This results in prompt being printed several times, which is frustrating.
I want to know if there's a way to temporarily disable keyboard input while time.sleep is going on, and then enable it afterwards. Something like this:
import time
disable_keyboard_input()
time.sleep(2)
enable_keyboard_input()
while True:
etc.
Does anyone know of a way to do this using Python? Thank you in advance!
I found this worked brilliantly:
import time
class keyboardDisable():
def start(self):
self.on = True
def stop(self):
self.on = False
def __call__(self):
while self.on:
msvcrt.getwch()
def __init__(self):
self.on = False
import msvcrt
disable = keyboardDisable()
disable.start()
time.sleep(10)
disable.stop()
It stops the user from typing anything; when you press a key on the keyboard, nothing happens.
The other 2 answers are perfect if you are using it to make a real software and want to diable keyboard input only in the output screen. However, if it's for personal usage or you want to disable the keyboard for the whole system, you can use this code:
import keyboard
import time
a = int(input("Enter the time (in seconds) for which you want to disable keyboard: "))
for i in range(150):
keyboard.block_key(i)
time.sleep(a)
Don't forget to run pip install keyboard in the terminal before executing this code otherwise, you will get an error.
Try this.
stdout = sys.stdout
sys.stdout = sys.stderr
time.sleep(2)
sys.stdout = stdout
while True:
pass
Didn't tried this. But I hope all that was typed before sleep is ended will sended to stderr... Don't sure, but maybe Python have access to linux's std/null?

Categories

Resources