Reputation: 36
I am writing a program with an infinite while loop that runs a function which takes input from the user and then prints to the console. I would like to be able to do something along the lines of having a separate piece of code that continually checks the time as a background process and at a certain time, prints a message to the console and asks whether you'd like to quit the program or continue the while loop. I assume I'd need multithreading or something along the lines of that.
def main():
while True:
x = input("Write Something: ")
print(x)
main()
Upvotes: 0
Views: 239
Reputation: 879391
Here is an attempt using Tim Peters' suggestion to use threading.Timer
:
import threading
check_done = False
def are_we_done_yet():
global check_done
print("quit now?")
check_done = True
t = threading.Timer(2.0, are_we_done_yet)
t.daemon = True
t.start()
t = threading.Timer(2.0, are_we_done_yet)
t.daemon = True
t.start()
while True:
response = raw_input('>>> ')
if check_done:
if response.lower().startswith('y'): break
check_done = False
One problem with the code above is that there is no way to distinguish input that the user intended for the >>>
prompt from the user's response to the question quit now?
.
If the user happened to be typing a sentence beginning with a y
when the quit now?
question pops up, then the user might unintentionally cause the program to quit.
So a cleaner solution might be to use a GUI:
import Tkinter as tk
import tkMessageBox
def are_we_done_yet():
if tkMessageBox.askyesno(title="Quit", message="Quit now?",
default=tkMessageBox.NO):
root.quit()
root.after(2000, are_we_done_yet)
root = tk.Tk()
root.geometry('300x200')
entry = tk.Text(root)
entry.pack()
entry.focus()
root.after(2000, are_we_done_yet)
root.mainloop()
Upvotes: 1
Reputation: 70592
Threads are good for this, and the background thread will spend most of its time sleeping. Here's something you can start with. You'll have lots of problems eventually - comes with the territory ;-)
import threading
timetoquit = False
iolock = threading.Lock()
class Watcher(threading.Thread):
def __init__(self, timeout):
threading.Thread.__init__(self)
self.timeout = timeout
self.waiter = threading.Event()
def run(self):
global timetoquit
while not timetoquit:
self.waiter.wait(self.timeout)
if timetoquit:
return
with iolock:
i = raw_input("want to quit? ")
if i.startswith("y") or i.startswith("Y"):
timetoquit = True
self.waiter.clear()
# Unused in this example, but you may want it someday ;-)
def cancel(self):
global timetoquit
timetoquit = True
self.waiter.set()
# this Watcher will ask every 10 seconds
watch = Watcher(10)
watch.start()
while not timetoquit:
# do stuff
# put console interaction in `with iolock` to
# prevent the main program and the thread from
# messing with the console at the same time
with iolock:
if not timetoquit:
whatever = raw_input("enter something ")
# do stuff
Upvotes: 2