How Do I Loop An Input In Python? - python

I have been searching and searching on how to figure out how to make an input or something go into a while loop. As in, the input() command won't stop my stopwatch. I have tried tkinter, pygame, and a couple other methods, but they just didn't work. If anyone can help me out, I would prefer something small and simple, if that's even possible. And to be specific on what I want to learn to do, is basically allowing, when any key is pressed, for it to instantly stop (preferably without hitting enter). Thanks, saddlepiggy!
Here is what I have so far, with nothing to activate the stopping:
#Setup (Variables and stuff)
hours = 0
minutes = 0
seconds = 0
import time
#Main Part of Code
print("Welcome to PyWatch, a stopwatch coded in Python!")
print("Press any key to start the stopwatch.")
print("Then, press any key to stop it!")
start = input("")
while hours < 48:
seconds = seconds + 1
time.sleep(1)
print(hours, "hours,", minutes, "minutes,", seconds, "seconds")
#If Statements for getting seconds/minutes/hours
if (seconds == 60):
minutes = minutes + 1
seconds = seconds - 60
if (minutes == 60):
hours =hours + 1
minutes = minutes - 60

Threading is what you want.
Create a second thread that waits for the input while your first thread handles your stopwatch code. Behold:
import threading, sys
def halt():
raw_input()
threading.Thread(target=halt).start()
while hours < 48 and threading.active_count() > 1:
seconds = seconds + 1
time.sleep(1)
# copy and past what you had before
Allow me to elaborate on what's happening: Thus far, all of the code you've written has been single threaded. This means only one line of code is executed at a time, there's only one thread of execution. Consequentially, your script can't multitask, it can't wait for input and print the time at the same time.
So when this line is evaluated
threading.Thread(target=halt).start()
The main thread creates a second thread of execution. Meanwhile, the main thread goes on and enters the while loop. The target parameter is the entry point of the thread, it's the starting point. It's analogous to if __name__ == "__main__:" for the main thread. Just as the main thread terminates when it reaches the end of if __name__ == "__main__:", our second thread will terminate once it reaches the end of halt().
The threading.active_count function tells you how many threads in are current in execution.

You can't do that in Python. You are asking for a keyboard event. Keyboard events are shipped with a GUI. This thread explains pretty much everything: QKeyPress event in PyQt
Or use an external application for your OS that can append output to a file that is read by your Python program in a loop. When a certain event is detected you can perform some actions. For Linux this tread explains: https://superuser.com/questions/248517/show-keys-pressed-in-linux

Related

How can I input a time and have the timer count down?

I am trying to run a while loop so I can run code while the timer is still counting down.I also want to see the timer as it counts down. I have tried to find something similar on stack overflow, but haven't been able to get the result I'm looking for.
print("Input minutes and seconds")
min = int(input("Minutes: "))
sec = int(input("Seconds: "))
while min & sec > 0:
# do some code
# I want the program to count down from whatever I input
print("")
You should run your timer on a different thread. If you don't need the timer to affect the main code being run this should work:
import threading
import time
def timer_function(seconds):
'''Countdown from number of seconds given'''
for t in range(seconds, -1, -1):
time.sleep(1)
print(t)
if __name__ == "__main__":
print("Input minutes and seconds")
min = int(input("Minutes: "))
sec = int(input("Seconds: "))
x = threading.Thread(target=timer_function, args=(min * 60 + sec,))
x.start()
# Run some other code in parallel with the timer
x.join() # will wait for the timer function to finish
print('All done')
If you need the timer to stop the main thread (the code being run on the main function) then you need send some signal through a variable from the timer thread.
There might be some libraries that handle thread timeouts better if you would like to look it up :)
Getting very precise timeout timing is somewhat troublesome, as the operation of reporting on the timing can affect the timing itself if not carefully written.
Something like this is often best accomplished with two threads in parallel
Making the threads "daemon threads" allows you to end them by quitting the program (otherwise the program will wait for them to be .join()ed)
You can rely on threading.Event() to clearly communicate into a thread and provide a .wait() method, which will either wait for a given timeout or immediately end when the event .is_set()
import threading
import time
def function_to_call(): # replace me with your function
time.sleep(1000)
def timer_fn(timeout, event, delay=5): # 5 seconds between reports
time_end = time.time() + timeout
while not event.is_set():
time_remaining = int(time_end - time.time())
if time_remaining <= 0:
return
print(f"{int(time_remaining)}s remaining")
event.wait((min(delay, time_remaining))) # wait for event
timeout = int(input("minutes: ") or 0) * 60 + int(input("seconds: ") or 0)
E = threading.Event() # Event to kill t2
# making t1 a daemon lets it not prevent shutdown
t1 = threading.Thread(target=function_to_call, daemon=True)
t2 = threading.Thread(target=timer_fn, args=(timeout, E), daemon=True)
# begin both threads
t1.start()
t2.start()
# wait for t1 to exit (but not t2)
t1.join(timeout=timeout)
# t1 may join faster by ending, otherwise reach here after timeout
E.set() # set the Event to quickly end t2 (timeout or t1 returned)
t2.join() # not technically necessary, but cleans up t2
# program quits and t1 is killed if it's still running
Note that the timing display is actually separate from the thread ending, and ending the function early is done here by stopping the program. The function will continue to run if the program is not stopped!
If more advanced task control is needed, consider
modifying your callable function to repeatedly check another threading.Event throughout it to see if it's time is up (yet)
use multiprocessing, which is much more featureful than threading, though it may need to copy memory into the new process, which can be slow if you have a tremendous amount
use subprocess, creating a script just for the purpose of a timed end (here you can kill the subprocess with a simple .kill() or setting a timeout= argument when creating it! (though again you'll find some inefficiency in copying/streaming input into and out of the new process)
use os.fork() and [os.kill()](https://docs.python.org/3/library/os.html#os.kill) to split your process (advanced, but usually much more efficient than multiprocessing` due to how memory is (or rather is not) copied)
if your function can be made asynchronous, which allows multiple tasks to collaborate in the same namespace similar to threading, but in a more friendly way (though how this behaves is fundamentally different from the other techniques given, it can be very efficient if you have many tasks which don't rely on local resources, such as a webserver or database)
Though further fundamentally different, you may find further or more benefit in designing your task to be a collection of work to iterate over (maybe in a list) and consider a library like tqdm to report on its status
Try this,
Code :
import time
print("Input minutes and seconds")
min = int(input("Minutes: "))
sec = int(input("Seconds: "))
t = min*60 + sec
while t :
mins, secs = divmod(t, 60)
timer = '{:02d}:{:02d}'.format(mins, secs)
print(timer, end="\r")
time.sleep(1)
t -= 1
print('Timer ended !!')
Output :
Input minutes and seconds
Minutes: 1
Seconds: 5
01:05
01:04
01:03
01:02
01:01
01:00
00:59
00:58
.
.
.
00:01
Timer ended !!
You should ideally use threads and spawn a daemon to keep track, but that might be overkill for your case. I've made a more simple implementation which is hopefully understandable, otherwise please ask and I'll improve the comments/explanation:
import time
set_time = int(input('For how many seconds do you want to run this?'))
start_time = time.time() # lets get the current time
inner_time = time.time() # Seperate vars so we don't overwrite the main loop
count = 0 #To keep track of how many seconds we've been going
while (time.time() - start_time) < set_time: #Lets run this until we've reached our time
if(time.time() - inner_time) >= 1: #If 1 sec has passed
inner_time = time.time() #Reset time
count += 1 #Increase second by 1
print("Code has been running for "+str(count)+" seconds") #Inform the user
#Do something here...
print(str(set_time)+" seconds have now elapsed") #Done and dusted
This is the output:
For how long do you want to run this?5
Code has been running for 1 seconds
Code has been running for 2 seconds
Code has been running for 3 seconds
Code has been running for 4 seconds
5 seconds have now elapsed

Python - Pause entire script every 10 minutes

Need a way to pause a script for 2 minutes after letting it run for 10 minutes first, and then have this process repeat itself. I need the script itself to continue running throughout the 10 minutes.
I tried using threading but found that it didn't actually pause the the rest of the script.
EDIT: Added code to give perspective. Hopefully this helps to explain my issue.
Your code has a nice loop where you can implant the pause, like so:
from datetime import datetime, timedelta
...
def start():
lastsleep = datetime.now() # <-- new
while True:
openBank()
gear()
invCheck()
timer = random.uniform(33, 37)
print("Sleep time: %s" % timer)
time.sleep(timer)
if (datetime.now() - lastsleep) > timedelta(minutes=10): # <-- new
time.sleep(2*60)
lastsleep = datetime.now()
Note that this will not sleep exactly after 10 minutes, but whenever 10 minutes are over and it reaches the checkpoint. This may be 10:12 or 13:47 minutes, depending on what the other code (openBank(), gear() etc.) does before.
Answer before code was shown:
The problem is: we have no information on how your code looks like.
If you have
something = getSomething()
something.DoSomeVeryExpensiveOperation() # takes 25 minutes
there's no good way to interrupt or pause that method after 10 minutes.
The only way I can think of as a generic method is like this:
use multiprocessing
monitor the process from outside
after 10 minutes, suspend all threads of the process
sleep 2 minutes
resume all threads of the process
Before you do that, you should know why you should never suspend a thread

I have some code and I would like some troubleshooting on it

My timer won't work properly, since it keeps printing forever, not what I want.
I've already tried re-organizing the script in many ways, but the result is always the same.
import time
CommandInput = input()
#execution [uptime]
def uptime(y):
while 1 == 1:
if (CommandInput == "uptime"):
print(y, " seconds")
y = y + 1
time.sleep(1)
uptime(9)
I wanted to make some sort of "background timer" that kept running from when the script was executed up to when it was closed, and if I typed a certain line in the input it would show the current number it is in. The problem is that it keeps printing the timer forever, for every single number it counts. I wanted to do a one-time thing, where you could wait as much as you want and type the input, which would show the number the timer is in.
Your current program has to wait for input() to finish. The compiler does not move past the second line until the user hits enter. Thus the functions starts once the input is finished.
This timer could be done several way, such as threading or timers. There are some examples of that here and here. For threading, you need one process for user inputs and one for timers. But the better and easier way is to to use a timer and store the current time. I believe the following code is somewhat similar to what you want:
import time
start_time = time.time()
def get_time():
current_time = time.time()
total = current_time - start_time
return total
while True:
CommandInput = input()
if CommandInput == "uptime":
y = get_time()
print(str(round(y)) + " seconds")
The variable start_time records the current time at the start. time.time() gets the current time in seconds on the computer. The get_time function is called after an input and sees how much time has pasted by subtracting the current time minus the start time. This way the you do not need multiple loops.
The while True loops just waits for the user input and then prints the time. This then repeats until the program is exited.
To write a script like that you would need to look into a module called asyncio (https://docs.python.org/3/library/asyncio.html), which would allow you to run multiple things at the same time.
Here is a asyncio hello world:
import asyncio
async def main():
print('Hello ...')
await asyncio.sleep(1)
print('... World!')
# Python 3.7+
asyncio.run(main())

How to make a countdown timer that runs in the background, which terminates the program when it runs out?

I am making a Who Wants to be a Millionare game in Python using graphics. I want the user to get 45 seconds per question to answer it. However, whenever I put a timer in my code it waits for 45 seconds first, then lets the user answer, instead of running in the background and letting the user answer at the same time.
Using the threading module to run multiple threads at once
You could use the Python threading module to make two things happen at once, thereby allowing the user to answer while the timer ticks down.
Some example code utilizing this:
from threading import Thread
from time import sleep
import sys
def timer():
for i in range(45):
sleep(1) #waits 45 seconds
sys.exit() #stops program after timer runs out, you could also have it print something or keep the user from attempting to answer any longer
def question():
answer = input("foo?")
t1 = Thread(target=timer)
t2 = Thread(target=question)
t1.start() #Calls first function
t2.start() #Calls second function to run at same time
It's not perfect, but this code should start two different threads, one asking a question and one timing out 45 seconds before terminating the program. More information on threading can be found in the docs. Hope this helps with your project!
Try using time.time(). This returns a the amount of seconds since January 1, 1970 in UNIXTime. You can then create a while loop such that:
initial_time = time.time()
while time.time()-initial_time < 45:
#Code
Hope this helped!

Making a timer in python whilst recording an input

I'm trying to create a program that runs in a similar format to the game show Countdown.
I have found various ways to create a timer, most successfully with the time.sleep command and a while loop.
However, the user needs to be able to input a word whilst the timer is going on, otherwise the user could take as long as they want to think of their word after the timer has stopped. Once the timer has stopped, whatever the user has typed in should be taken as their word. I haven't found any kind of solution for this yet as python runs sequentially so it's difficult to have a timer and an input at the same time.
This worked for me previously... Uses time.time(). If this isn't what you are looking for maybe check out perf_counter()
import msvcrt
import time
def Countdown():
p = 3.00
alarm = time.time() + p
text = []
while True:
n = time.time()
if msvcrt.kbhit():
text.append(msvcrt.getche())
if n < alarm:
print(round(alarm - n))
else:
print("Time's up!")
break
Countdown()
Making a countdown timer with Python and Tkinter?

Categories