Come impostare il limite di tempo raw_input [duplicato]
-
05-10-2019 - |
Domanda
Questa domanda ha già una risposta qui:
- Timeout su una funzione di chiamata 14 risposte
in pitone, c'è un modo per, in attesa di un input dell'utente, conteggio tempo in modo che dopo, diciamo 30 secondi, la funzione raw_input()
viene saltata automaticamente?
Soluzione
Il href="http://docs.python.org/library/signal.html?highlight=signal#signal.alarm" rel="noreferrer"> signal.alarm funzione Threading.Timer invece, utilizzando thread.interrupt_main per inviare un KeyboardInterrupt
al thread principale dal thread del timer. Cioè:.
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
questo restituirà Nessuno se il tempo di 30 secondi fuori o l'utente decida esplicitamente di colpo il controllo-C di rinunciare a introdurre nulla, ma sembra OK per trattare i due casi allo stesso modo (se avete bisogno di distinguere, è possibile utilizzare per il timer in funzione del vostro proprio che, prima di interrompere il thread principale, record da qualche parte il fatto che un timeout ha è accaduto, e nel vostro gestore per l'accesso KeyboardInterrupt
che "da qualche parte" di discriminare che dei due casi si è verificato).
Modifica : avrei giurato che questo era a lavorare, ma devo aver sbagliato - il codice di cui sopra omette la timer.start()
ovviamente necessaria, e , anche con esso posso 't farlo funzionare più. select.select
sarebbe l'ovvio altra cosa da provare, ma non funziona su un "file normale" (tra cui stdin) in Windows -. in Unix funziona su tutti i file, in Windows, solo sui socket
Quindi non so come fare un cross-platform "input crudo con timeout". A specifico per Windows può essere costruito con un polling loop stretto MSVCRT. kbhit , eseguendo una msvcrt.getche
(e controllando se è un ritorno per indicare l'uscita che è fatto, nel qual caso si rompe fuori dal giro, altrimenti si accumula e rimane in attesa) e il controllo del tempo di time out, se necessario. Non posso prova perché non ho macchina Windows (sono tutti i Mac e quelli di Linux), ma qui la codice non testato Vorrei suggerire:
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 in un commento dice che non vuole return None
su timeout, ma qual è l'alternativa? Sollevando un'eccezione? Tornando un valore predefinito diverso? Qualunque sia alternativa che vuole lui può chiaramente messo in luogo della mia return None
; -).
Se non si vuole il tempo solo perché l'utente sta digitando lentamente (al contrario di non digitare a tutti -!), Si potrebbe ricalcolare finishat dopo ogni immissione dei caratteri di successo <. / p>
Altri suggerimenti
Ho trovato una soluzione a questo problema in un blog postare . Ecco il codice da questo post del 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 ''
Si prega di notare:. Questo codice unico lavoro su * nix sistemi operativi
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
Come si è auto definito ... eseguirlo in linea del prompt dei comandi, spero che otterrà la risposta leggere questo pitone doc sarà cristallino quello che è appena accaduto in questo codice !!
La funzione di ingresso () è progettato per attendere che l'utente di inserire qualcosa (almeno il tasto [Invio]).
Se non siete morti insieme all'ingresso uso (), qui di seguito è una soluzione molto più leggero usando Tkinter. In Tkinter, finestre di dialogo (e qualsiasi widget di) possono essere distrutti dopo un certo tempo.
Ecco un esempio:
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 maledice esempio che prende per un test di matematica a tempo
#!/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)
sotto Linux poteva usare maledizioni e funzione getch, la sua non bloccante. vedi getch ()
https://docs.python.org/2/library/curses.html
funzione che attende l'input da tastiera per x secondi (si deve inizializzare una finestra di maledizioni (WIN1) prima!
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