python - que - Cómo establecer el límite de tiempo en raw_input
raw_input python 3 (6)
Esta pregunta ya tiene una respuesta aquí:
- Tiempo de espera en una llamada de función 12 respuestas
en python, ¿hay alguna manera de, mientras se espera la entrada del usuario, contar el tiempo para que, después de, digamos 30 segundos, la función raw_input()
automáticamente?
Encontré una solución a este problema en una publicación de blog . Aquí está el código de esa publicación de 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 ''''
Tenga en cuenta: este código solo funcionará en los sistemas operativos * nix .
La función signal.alarm , en la que se basa la solución recomendada de @ jer, desafortunadamente es solo de Unix. Si necesita una solución multiplataforma o específica de Windows, puede thread.interrupt_main en threading.Timer cambio, use thread.interrupt_main para enviar un KeyboardInterrupt
al hilo principal desde el hilo del temporizador. Es decir:
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
esto devolverá None, ya sea que transcurran 30 segundos o que el usuario decida explícitamente presionar control-C para dejar de ingresar cualquier cosa, pero parece correcto tratar los dos casos de la misma manera (si necesita distinguir, podría usar para el temporizador una función propia que, antes de interrumpir el hilo principal, registra en alguna parte el hecho de que ha transcurrido un tiempo de espera, y en su controlador para KeyboardInterrupt
acceda a "algún lugar" para discriminar cuál de los dos casos ocurrió).
Editar : Podría haber jurado que esto funcionaba, pero debo haberme equivocado: el código anterior omite el timer.start()
, obviamente necesario, e incluso con él no puedo hacerlo funcionar más. select.select
sería lo obvio que hay que probar, pero no funcionará en un "archivo normal" (incluido stdin) en Windows, en Unix funciona en todos los archivos, en Windows, solo en los sockets.
Así que no sé cómo hacer una "entrada sin procesar con tiempo de espera multiplataforma". Se puede construir un msvcrt.kbhit específico de Windows con un sondeo de bucle cerrado msvcrt.kbhit , realizando un msvcrt.getche
(y comprobando si es un retorno para indicar que la salida está completa, en cuyo caso se rompe el bucle, de lo contrario se acumula y sigue esperando ) y verificar el tiempo de espera si es necesario. No puedo realizar pruebas porque no tengo una máquina con Windows (todas son Mac y Linux), pero aquí el código no probado que sugeriría:
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
El OP en un comentario dice que no quiere return None
después del tiempo de espera, pero ¿cuál es la alternativa? ¿Planteando una excepción? ¿Devolviendo un valor por defecto diferente? Cualquier alternativa que él quiera, puede ponerla claramente en lugar de mi return None
;-).
Si no desea agotar el tiempo de espera solo porque el usuario está escribiendo lentamente (en lugar de, ¡no escribiendo en absoluto! -), puede volver a calcular el final después de cada entrada de caracteres exitosa.
La función input () está diseñada para esperar que el usuario ingrese algo (al menos la tecla [Enter]).
Si no está configurado para usar input (), a continuación se muestra una solución mucho más ligera usando tkinter. En tkinter, los cuadros de diálogo (y cualquier widget) se pueden destruir después de un tiempo determinado.
Aquí hay un ejemplo :
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 ejemplo de maldiciones que requiere una prueba de matemáticas cronometrada
#!/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)
bajo linux se podría usar la función curses y getch, no es un bloqueo. ver getch ()
https://docs.python.org/2/library/curses.html
función que espera la entrada del teclado por x segundos (¡primero tiene que inicializar una ventana de maldiciones (win1)!
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
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
Como está autodefinido ... ejecútalo en el indicador de la línea de comandos, espero que obtengas la respuesta. Lee este documento de Python. ¡ Vas a tener muy claro lo que acaba de suceder en este código!