Comment définir la limite de temps sur raw_input [double]
-
05-10-2019 - |
Question
Cette question a déjà une réponse ici:
- délai d'attente sur un appel de fonction 14 réponses
en python, est-il un moyen de, en attendant une entrée utilisateur, compter le temps de sorte qu'après, disons 30 secondes, la fonction raw_input()
est automatiquement ignorée?
La solution
La fonction signal.alarm , sur lequel @ solution recommandée Jer est basée, est malheureusement Unix seulement. Si vous avez besoin d'une solution multi-plateforme ou spécifique à Windows, vous pouvez baser sur threading.Timer au lieu, en utilisant thread.interrupt_main pour envoyer un KeyboardInterrupt
au fil conducteur du fil de minuterie. I.e.:.
import thread
import threading
def raw_input_with_timeout(prompt, timeout=30.0):
print prompt,
timer = threading.Timer(timeout, thread.interrupt_main)
astring = None
try:
timer.start()
astring = raw_input(prompt)
except KeyboardInterrupt:
pass
timer.cancel()
return astring
retourne None si le 30 secondes le temps ou l'utilisateur décide explicitement de frapper le contrôle-C pour renoncer à entrer quoi que ce soit, mais il semble OK pour traiter les deux cas de la même manière (si vous avez besoin de faire la distinction, vous pouvez utiliser pour la minuterie en fonction de votre propre que, avant d'interrompre le thread principal, les dossiers quelque part le fait qu'un délai d'attente a est arrivé, et dans votre gestionnaire pour l'accès KeyboardInterrupt
que « quelque part » discriminer qui des deux cas se sont présentés).
Modifier : Je aurait pu jurer ce fonctionnait, mais je devais avoir tort - le code ci-dessus passe sous silence le timer.start()
évidemment nécessaire, et même avec elle que je peux « t le faire fonctionner plus. select.select
serait l'évidence autre chose à essayer, mais il ne fonctionnera pas sur un « fichier normal » (y compris stdin) dans Windows -. Unix il fonctionne sur tous les fichiers, sous Windows, uniquement sur les sockets
Je ne sais pas comment faire une croix-plate-forme « entrée brute avec délai d'attente ». Une fenêtre spécifique peut être construit avec un msvcrt. kbhit , effectuer une msvcrt.getche
(et vérifier si elle est un retour pour indiquer la sortie est fait, dans ce cas, il se casse de la boucle, sinon accumule et garde en attente) et vérifier le temps en temps si nécessaire. Je ne peux pas tester parce que je n'ai pas machine Windows (ils sont tous les Mac et les Linux), mais ici code non testé Je suggère:
import msvcrt
import time
def raw_input_with_timeout(prompt, timeout=30.0):
print prompt,
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
L'OP dans un commentaire dit qu'il ne veut pas return None
sur délai d'attente, mais quelle est l'alternative? Raising une exception? De retour une valeur par défaut différente? Quelle que soit autre qu'il veut, il peut clairement mettre en place de mon return None
; -).
Si vous ne voulez pas le temps juste parce que l'utilisateur tape lentement -, vous pourriez recalcule finishat après chaque entrée de caractère avec succès <(par opposition à, non pas taper du tout!). / p>
Autres conseils
J'ai trouvé une solution à ce problème dans un blog poster . Voici le code de ce blog:
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 ''
S'il vous plaît noter:. ce code ne de travail sur les * nix OSs
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
Comme il est auto défini ... l'exécuter en ligne de commande rapide, je l'espère, vous obtiendrez la réponse lire doc python vous être très clair ce qui vient de se passer dans ce Code !!
La fonction d'entrée () est conçu pour attendre que l'utilisateur d'entrer quelque chose (au moins la touche [Entrée]).
Si vous n'êtes pas mort mis à l'entrée d'utilisation (), ci-dessous est une solution beaucoup plus léger en utilisant tkinter. Dans tkinter, les boîtes de dialogue (et ne importe quel widget) peuvent être détruits après un certain temps.
Voici un exemple:
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')
Un exemple maudit qui prend pour un test de mathématiques chronométré
#!/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)
sous Linux pourrait utiliser une fonction sorts et getch, son blocage non. voir getch ()
https://docs.python.org/2/library/curses.html
fonction qui attend l'entrée du clavier pendant x secondes (vous devez initialiser une fenêtre malédictions (de win1) d'abord!
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