This question already has answers here:
Keyboard input with timeout?
(28 answers)
Closed 8 years ago.
I want to do a raw_input('Enter something: .'). I want it to sleep for 3 seconds and if there's no input, then cancel the prompt and run the rest of the code. Then the code loops and implements the raw_input again. I also want it to break if the user inputs something like 'q'.
There's an easy solution that doesn't use threads (at least not explicitly): use select to know when there's something to be read from stdin:
import sys
from select import select
timeout = 10
print "Enter something:",
rlist, _, _ = select([sys.stdin], [], [], timeout)
if rlist:
s = sys.stdin.readline()
print s
else:
print "No input. Moving on..."
Edit[0]: apparently this won't work on Windows, since the underlying implementation of select() requires a socket, and sys.stdin isn't. Thanks for the heads-up, #Fookatchu.
If you're working on Windows you can try the following:
import sys, time, msvcrt
def readInput( caption, default, timeout = 5):
start_time = time.time()
sys.stdout.write('%s(%s):'%(caption, default));
input = ''
while True:
if msvcrt.kbhit():
chr = msvcrt.getche()
if ord(chr) == 13: # enter_key
break
elif ord(chr) >= 32: #space_char
input += chr
if len(input) == 0 and (time.time() - start_time) > timeout:
break
print '' # needed to move to next line
if len(input) > 0:
return input
else:
return default
# and some examples of usage
ans = readInput('Please type a name', 'john')
print 'The name is %s' % ans
ans = readInput('Please enter a number', 10 )
print 'The number is %s' % ans
I have some code which makes a countdown app with a tkinter entry box and button so they can enter something and hit the button, if the timer runs out the tkinter window closes and tells them they ran out of time.
I think most other solutions to this problem don't have a window which pops up so thought id add to the list :)
with raw_input() or input(), it isn't possible as it stops at the input section, until it receives input, then it carries on...
I have taken some code from the following link:
Making a countdown timer with Python and Tkinter?
I used Brian Oakley's answer to this problem and added the entrybox etc.
import tkinter as tk
class ExampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
def well():
whatis = entrybox.get()
if whatis == "": # Here you can check for what the input should be, e.g. letters only etc.
print ("You didn't enter anything...")
else:
print ("AWESOME WORK DUDE")
app.destroy()
global label2
label2 = tk.Button(text = "quick, enter something and click here (the countdown timer is below)", command = well)
label2.pack()
entrybox = tk.Entry()
entrybox.pack()
self.label = tk.Label(self, text="", width=10)
self.label.pack()
self.remaining = 0
self.countdown(10)
def countdown(self, remaining = None):
if remaining is not None:
self.remaining = remaining
if self.remaining <= 0:
app.destroy()
print ("OUT OF TIME")
else:
self.label.configure(text="%d" % self.remaining)
self.remaining = self.remaining - 1
self.after(1000, self.countdown)
if __name__ == "__main__":
app = ExampleApp()
app.mainloop()
I know what I added was a bit lazy but it works and it is an example only
This code works for Windows with Pyscripter 3.3
For rbp's answer:
To account for input equal to a Carriage Return simply add a nested condition:
if rlist:
s = sys.stdin.readline()
print s
if s == '':
s = pycreatordefaultvalue
Related
Clarificaition
This is a repost of my previous question as I am extremely desperate to receive an answer to my problem. I am quite new and if this is against any of the rules, please inform me as I would remove this post if so.
I want to create a quiz-like program where the user would be able to see the countdown timer ticking down every second while they can input their answer at any time. According to my previous post regarding this question, I've tried using threading in my code. Here is a sample of my code.
from threading import Thread
import time
import sys
def func1():
t = 10
for t in range (t,1,-1):
sys.stdout.write('\r' + str(t))
sys.stdout.flush()
time.sleep(1)
if __name__ == '__main__':
Thread(target = func1).start()
answer = input("\tEnter: ")
It does function, but the problem is that the user input is forced to return back (\r) while the timer doesn't properly remove the '0' of the 10 which is not what I desire. Here is the output:
It would be a tremendous help if you could suggest a solution to this problem. Thank you in advance.
After some messing around, I came up with this.
If you would like me to edit this to make it work without the windows, let me know.
import time
import tkinter
from tkinter import messagebox
from tkinter import *
from tkinter import ttk
from threading import Thread
def clear():
print('\033[H\033[J', end='')
run = True
def timer():
tim = int(input("Type how long the countdown should last in seconds: "))
clear()
count = 0
while count < tim and run == True:
clear()
b1 = (tim-count)
c = (str(b1),"second(s) left")
win = Tk()
win = Tk()
win.attributes('-fullscreen', True)
if run == False:
win.destroy()
Label(win, text= c,
font=('Helvetica 20 bold')).pack(pady=20)
win.after(1000,lambda:win.destroy())
win.mainloop()
time.sleep(1)
count += 1
def take_input():
inpu = input()
#Your code
def time_input():
global run
while run == True:
t1 = Thread(target=timer)
t2 = Thread(target=take_input)
t1.start()
t2.start()
t2.join()
thread_running = False
run = False
time_input()
Hope this helps, and you're welcome. 乇卩丨匚卄乂尺
(To stop the window from being fullscreen, change the (window).attributes('-fullscreen', True) to (window).geometry(500x500) or whatever you wish.
display a double 3 time method for tracking analysis with frameworks
we need to find the x for y
and describe why it happeneds that way
do not quote for 32 x 8. Most of the If the player guess a letter which exists in the word, the script writes it in all its correct positions. The player has 10 turns to guess the word. You can easily customize the game by changing the variables.live coding demo portion of the course and showing the process of coding a
#importing the time module
import time
#welcoming the user
name = raw_input("What is your name? ")
print "Hello, " + name, "Time to play hangman!"
print "
"
#wait for 1 second
time.sleep(1)
print "Start guessing..."
time.sleep(0.5)
#here we set the secret
word = "secret"
#creates an variable with an empty value
guesses = ''
#determine the number of turns
turns = 10
# Create a while loop
#check if the turns are more than zero
while turns > 0:
# make a counter that starts with zero
failed = 0
# for every character in secret_word
for char in word:
# see if the character is in the players guess
if char in guesses:
# print then out the character
print char,
else:
# if not found, print a dash
print "_",
# and increase the failed counter with one
failed += 1
# if failed is equal to zero
# print You Won
if failed == 0:
print "
You won"
# exit the script
break
print
# ask the user go guess a character
guess = raw_input("guess a character:")
# set the players guess to guesses
guesses += guess
# if the guess is not found in the secret word
if guess not in word:
# turns counter decreases with 1 (now 9)
turns -= 1
# print wrong
print "Wrong
"
# how many turns are left
print "You have", + turns, 'more guesses'
# if the turns are equal to zero
if turns == 0:
# print "You Lose"
print "You Lose
"
The mainloop is a function of the root window, so you should assign a name to it:
if __name__ == '__main__':
url = 'https://api.exchangerate-api.com/v4/latest/USD'
converter = MikesMagicalConverter(url)
app = App(converter) # Assing a name to root window
app.mainloop() # Run root window mainloop
When you create the button you should provide a reference to the master:
buttonExample = tk.Button(self, # Provide reference to master
text="Create new window",
command=lambda:self.currency_converter.createNewWindow(self)) # Pass reference
buttonExample.pack()
The command argument is a bit trickier; the class MikesMagicalConverter is not a widget and does not inherit from tkiner so you'll have to pass a reference to use as master to the Toplevel window.
You must provide a self parameter to the createNewWindow() method.
def createNewWindow(self, master):
newWindow = tk.Toplevel(master) # Using reference as master
labelExample = tk.Label(newWindow, text = "New Window")
buttonExample = tk.Button(newWindow, text = "New Window button")
labelExample.pack()
buttonExample.pack()
In general: many of your lines are way to long, makes the code hard to read.
With those changes the code will still generate error, but the button and Toplevel window pops up. I'm thinking you might rather separate the currency calculations from the GUI code.
I'm looking to move a motorised slider using a Raspberry Pi. However, while debugging the system I was wondering if it is possible to use:
target = int(raw_input(<message>))
In a way that message could dynamically change before the user inputs a value. For me, it would be great to see the current value that is read from the slider in this <message> for example.
And if that isn't possible, is it possible to have a line printed above or below the raw_input that remains changing while the system waits for the users' input?
You can find that as a non-blocking input.
Here is a solution from stack overflow, which uses threads
I did a little modified solution, it still needs some tweaking, but its more or less what you have to do.
python
import threading
import time
import random
userInput = ""
finished = False
sensorValue = 100
previousValue = 0
def Listener():
global userInput, finished, sensorValue
userInput = raw_input(sensorValue)
if len(userInput) > 0:
print(len(userInput))
finished = True
else:
finished = False
while True:
if sensorValue != previousValue:
print("Received new slider info. SliderValue is {}".format(sensorValue))
previousValue = sensorValue
else:
print("No new info from slider. Sleeping two seconds.")
if not finished:
listener = threading.Thread(target=Listener)
listener.start()
else:
break
if random.randint(0,1) == 1:
sensorValue += 10
time.sleep(2)
See if that answers your question! :)
I'm new to Python and have been googling for a couple of days and read all I can find on this forum. Might be that I don't understand it all but I haven't found a solution to my problem yet. Ask for forgiveness already if there's an answer already to my problem, then I haven't understood it.
I want to make a Pause function for my program Tennismatch. The program will when it's being run print the score of a tennis match like this: "15-0, 15-15 etc ongoing till the match ends. It will print the score line by line.
I want the user to be able to pause after x number of balls, games, etc. So I don't know when the user wants to pause and after the user has paused I want the user to be able to resume the tennismatch where it was.
Have seen the time.sleep() but as I have understood it you must know when you want to pause to use this and it also ain't an indefinetie pause like I want. With input() it's the same.
Am going to make a GUI later on when the code is finished. Happy for anything that leads me to solving my problem.
I use Windows and Python 3.42 and run the program in Shell.
A piece of the code (haven't written it all yet, it's more of a general situation when something is being printed line after line for some time and want to be able do pause in the CIL:
#self.__points = [0,0]
def playGame(self):
if self.server == True: #self.server is either True or False when someone calls playGame()
server = self.player_1.get_win_serve() #self.player_1 = an object of a class Player():
else:
server = self.player_2.get_win_serve() #get_win_serve() method returns the probability to win his serv (1-0)
while (0 < self.__points[0] - self.__points[1] >= 2 or 0 < self.__points[1] - self.__points[0] >= 2) and (self.__points[1] >= 4 or self.__points[0] >= 4):
x = random.uniform(0,1)
if x > 0 and x < server:
self.__points[0] += 1
else:
self.__points[1] += 1
# print('The score, by calling a score() function that I haven't written yet')
For dealing with events in main loop you need to make a separated thread which capture input or any other event.
import sys
from sys import stdin
from time import sleep
from threading import Thread
from Queue import Queue, Empty
def do_something():
sleep(1)
print 42
def enqueue_output(queue):
while True:
# reading line from stdin and pushing to shared queue
input = stdin.readline()
print "got input ", input
queue.put(input)
queue = Queue()
t = Thread(target=enqueue_output, args=(queue,))
t.daemon = True
t.start()
pause = False
try:
while True:
try:
command = queue.get_nowait().strip()
print 'got from queue ', command
except Empty:
print "queue is empty"
command = None
if command:
if command == 'p':
pause = True
if command == 'u':
pause = False
if not pause:
print pause
do_something()
except KeyboardInterrupt:
sys.exit(0)
I came up with the following.
while True:
try:
## Keep doing something here
## your regular code
print '.',
except KeyboardInterrupt:
## write or call pause function which could be time.sleep()
print '\nPausing... (Hit ENTER to continue, type quit to exit.)'
try:
response = raw_input()
if response.lower() == 'quit':
break
print 'Quitting...'
except KeyboardInterrupt:
print 'Resuming...'
continue
The Event loop might as well be the code I wrote with.
I don't see any user input so I assume that x emulates it. To pause the game if x < 0.1 and to unpause(/resume) it if x > 0.9, you could:
while your_condition(self.__points):
x = random.random()
if x < 0.1: # pause
self.pause()
elif x > 0.9: # resume
self.resume()
if self.is_paused:
continue # do nothing else only wait for input (`x`)
# assume your_condition() has no side-effects
# here's what the resumed version does:
print("...")
# change self.__points, etc
where pause(), resume(), is_paused() methods could be implemented as:
def __init__(self):
self.is_paused = False
def pause(self):
self.is_paused = True
def resume(self):
self.is_paused = False
as you can see the implementation is very simple.
in python, is there a way to, while waiting for a user input, count time so that after, say 30 seconds, the raw_input() function is automatically skipped?
The signal.alarm function, on which #jer's recommended solution is based, is unfortunately Unix-only. If you need a cross-platform or Windows-specific solution, you can base it on threading.Timer instead, using thread.interrupt_main to send a KeyboardInterrupt to the main thread from the timer thread. I.e.:
import thread
import threading
def raw_input_with_timeout(prompt, timeout=30.0):
print(prompt, end=' ')
timer = threading.Timer(timeout, thread.interrupt_main)
astring = None
try:
timer.start()
astring = input(prompt)
except KeyboardInterrupt:
pass
timer.cancel()
return astring
this will return None whether the 30 seconds time out or the user explicitly decides to hit control-C to give up on inputting anything, but it seems OK to treat the two cases in the same way (if you need to distinguish, you could use for the timer a function of your own that, before interrupting the main thread, records somewhere the fact that a timeout has happened, and in your handler for KeyboardInterrupt access that "somewhere" to discriminate which of the two cases occurred).
Edit: I could have sworn this was working but I must have been wrong -- the code above omits the obviously-needed timer.start(), and even with it I can't make it work any more. select.select would be the obvious other thing to try but it won't work on a "normal file" (including stdin) in Windows -- in Unix it works on all files, in Windows, only on sockets.
So I don't know how to do a cross-platform "raw input with timeout". A windows-specific one can be constructed with a tight loop polling msvcrt.kbhit, performing a msvcrt.getche (and checking if it's a return to indicate the output's done, in which case it breaks out of the loop, otherwise accumulates and keeps waiting) and checking the time to time out if needed. I cannot test because I have no Windows machine (they're all Macs and Linux ones), but here the untested code I would suggest:
import msvcrt
import time
def raw_input_with_timeout(prompt, timeout=30.0):
print(prompt, end=' ')
finishat = time.time() + timeout
result = []
while True:
if msvcrt.kbhit():
result.append(msvcrt.getche())
if result[-1] == '\r': # or \n, whatever Win returns;-)
return ''.join(result)
time.sleep(0.1) # just to yield to other processes/threads
else:
if time.time() > finishat:
return None
The OP in a comment says he does not want to return None upon timeout, but what's the alternative? Raising an exception? Returning a different default value? Whatever alternative he wants he can clearly put it in place of my return None;-).
If you don't want to time out just because the user is typing slowly (as opposed to, not typing at all!-), you could recompute finishat after every successful character input.
I found a solution to this problem in a blog post. Here's the code from that blog post:
import signal
class AlarmException(Exception):
pass
def alarmHandler(signum, frame):
raise AlarmException
def nonBlockingRawInput(prompt='', timeout=20):
signal.signal(signal.SIGALRM, alarmHandler)
signal.alarm(timeout)
try:
text = raw_input(prompt)
signal.alarm(0)
return text
except AlarmException:
print '\nPrompt timeout. Continuing...'
signal.signal(signal.SIGALRM, signal.SIG_IGN)
return ''
Please note: this code will only work on *nix OSs.
The input() function is designed to wait for the user to enter something (at least the [Enter] key).
If you are not dead set to use input(), below is a much lighter solution using tkinter. In tkinter, dialog boxes (and any widget) can be destroyed after a given time.
Here is an example :
import tkinter as tk
def W_Input (label='Input dialog box', timeout=5000):
w = tk.Tk()
w.title(label)
W_Input.data=''
wFrame = tk.Frame(w, background="light yellow", padx=20, pady=20)
wFrame.pack()
wEntryBox = tk.Entry(wFrame, background="white", width=100)
wEntryBox.focus_force()
wEntryBox.pack()
def fin():
W_Input.data = str(wEntryBox.get())
w.destroy()
wSubmitButton = tk.Button(w, text='OK', command=fin, default='active')
wSubmitButton.pack()
# --- optionnal extra code in order to have a stroke on "Return" equivalent to a mouse click on the OK button
def fin_R(event): fin()
w.bind("<Return>", fin_R)
# --- END extra code ---
w.after(timeout, w.destroy) # This is the KEY INSTRUCTION that destroys the dialog box after the given timeout in millisecondsd
w.mainloop()
W_Input() # can be called with 2 parameter, the window title (string), and the timeout duration in miliseconds
if W_Input.data : print('\nYou entered this : ', W_Input.data, end=2*'\n')
else : print('\nNothing was entered \n')
from threading import Timer
def input_with_timeout(x):
def time_up():
answer= None
print('time up...')
t = Timer(x,time_up) # x is amount of time in seconds
t.start()
try:
answer = input("enter answer : ")
except Exception:
print('pass\n')
answer = None
if answer != True: # it means if variable have somthing
t.cancel() # time_up will not execute(so, no skip)
input_with_timeout(5) # try this for five seconds
As it is self defined... run it in command line prompt , I hope you will get the answer
read this python doc you will be crystal clear what just happened in this code!!
A curses example which takes for a timed math test
#!/usr/bin/env python3
import curses
import curses.ascii
import time
#stdscr = curses.initscr() - Using curses.wrapper instead
def main(stdscr):
hd = 100 #Timeout in tenths of a second
answer = ''
stdscr.addstr('5+3=') #Your prompt text
s = time.time() #Timing function to show that solution is working properly
while True:
#curses.echo(False)
curses.halfdelay(hd)
start = time.time()
c = stdscr.getch()
if c == curses.ascii.NL: #Enter Press
break
elif c == -1: #Return on timer complete
break
elif c == curses.ascii.DEL: #Backspace key for corrections. Could add additional hooks for cursor movement
answer = answer[:-1]
y, x = curses.getsyx()
stdscr.delch(y, x-1)
elif curses.ascii.isdigit(c): #Filter because I only wanted digits accepted
answer += chr(c)
stdscr.addstr(chr(c))
hd -= int((time.time() - start) * 10) #Sets the new time on getch based on the time already used
stdscr.addstr('\n')
stdscr.addstr('Elapsed Time: %i\n'%(time.time() - s))
stdscr.addstr('This is the answer: %s\n'%answer)
#stdscr.refresh() ##implied with the call to getch
stdscr.addstr('Press any key to exit...')
curses.wrapper(main)
under linux one could use curses and getch function, its non blocking.
see getch()
https://docs.python.org/2/library/curses.html
function that waits for keyboard input for x seconds (you have to initialize a curses window (win1) first!
import time
def tastaturabfrage():
inittime = int(time.time()) # time now
waitingtime = 2.00 # time to wait in seconds
while inittime+waitingtime>int(time.time()):
key = win1.getch() #check if keyboard entry or screen resize
if key == curses.KEY_RESIZE:
empty()
resize()
key=0
if key == 118:
p(4,'KEY V Pressed')
yourfunction();
if key == 107:
p(4,'KEY K Pressed')
yourfunction();
if key == 99:
p(4,'KEY c Pressed')
yourfunction();
if key == 120:
p(4,'KEY x Pressed')
yourfunction();
else:
yourfunction
key=0
This is for newer python versions, but I believe it will still answer the question. What this does is it creates a message to the user that the time is up, then ends the code. I'm sure there's a way to make it skip the input rather than completely end the code, but either way, this should at least help...
import sys
import time
from threading import Thread
import pyautogui as pag
#imports the needed modules
xyz = 1 #for a reference call
choice1 = None #sets the starting status
def check():
time.sleep(15)#the time limit set on the message
global xyz
if choice1 != None: # if choice1 has input in it, than the time will not expire
return
if xyz == 1: # if no input has been made within the time limit, then this message
# will display
pag.confirm(text = 'Time is up!', title = 'Time is up!!!!!!!!!')
sys.exit()
Thread(target = check).start()#starts the timer
choice1 = input("Please Enter your choice: ")