Cómo establecer límite de tiempo en raw_input [duplicado]
-
05-10-2019 - |
Pregunta
Esta pregunta ya tiene una respuesta aquí:
- de espera de una llamada a la función 14 respuestas
en Python, ¿hay una manera de, a la espera de una entrada de usuario, cuentan el tiempo de manera que después de, digamos 30 segundos, la función raw_input()
se salta automáticamente?
Solución
El href="http://docs.python.org/library/signal.html?highlight=signal#signal.alarm" rel="noreferrer"> signal.alarm función , en la que @ solución recomendada de jer se basa, por desgracia, es sólo UNIX. Si necesita una solución multiplataforma o específico para Windows, puede basar en threading.Timer lugar, utilizando thread.interrupt_main enviar un KeyboardInterrupt
a que el flujo principal del hilo 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
este devolverá None si el 30 segundos el tiempo de espera o el usuario decide explícitamente a golpe de control-C para renunciar a ingresar nada, pero parece que está bien para tratar los dos casos de la misma manera (si es necesario distinguir, se puede usar para el temporizador en función de su cuenta que, antes de interrumpir el hilo principal, registros de alguna parte del hecho de que un tiempo de espera tiene sucedido, y en el controlador de acceso KeyboardInterrupt
que "en algún lugar" para discriminar qué de los dos casos ocurrido).
Editar : Yo podría haber jurado que era trabajar pero debe haber sido un error - el código anterior omite la timer.start()
necesaria obviamente- y a pesar de que pueda 't hacer que funcione más. select.select
sería la otra cosa obvia a probar, pero no va a funcionar en un "archivo normal" (incluyendo la entrada estándar) en Windows -. en Unix funciona en todos los archivos, en Windows, únicamente conexiones
Así que no sé cómo hacer una multiplataforma "entrada sin procesar con el tiempo de espera". A uno específico para Windows puede ser construido con un sondeo de bucle estrecho msvcrt. kbhit , realizando una msvcrt.getche
(y comprobar si se trata de un retorno para indicar la salida que está hecho, en cuyo caso se rompe fuera del circuito, de lo contrario se acumula y queda a la espera) y comprobando el tiempo para el tiempo de espera si es necesario. No puedo prueba porque no tengo máquina de Windows (son todos los Mac y los de Linux), pero aquí la código no probado Yo 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 PO en un comentario dice que no quiere return None
al tiempo de espera, pero ¿cuál es la alternativa? Lanzar una excepción? La devolución de un valor predeterminado diferente? Cualquiera que sea alternativa quiere puede poner claramente en lugar de mi return None
; -).
Si no desea que el tiempo de espera sólo porque el usuario está escribiendo lentamente (en oposición a, no escribir en absoluto! -), que podría volver a calcular finishat después de cada entrada de caracteres éxito <. / p>
Otros consejos
He encontrado una solución a este problema en un blog publicar . Aquí está el código de esa entrada en el 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 único trabajo en * nix sistemas operativos
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
A medida que se auto define ... ejecutarlo en la línea de comandos del sistema, espero que obtendrá la respuesta leer este doc pitón que sea muy clara de lo que acaba de ocurrir en este código !!
La función de entrada () está diseñado para esperar a que el usuario introduzca algo (al menos la tecla [Enter]).
Si no está totalmente en uso a la entrada (), a continuación es una solución mucho más ligero usando tkinter. En tkinter, cuadros de diálogo (y cualquier tipo de artilugio) pueden ser destruidos después de un tiempo determinado.
Este es 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')
A maldice ejemplo que toma para un examen de matemáticas temporizada
#!/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 uno podría usar maldiciones y función getch, su no bloqueo. ver getch ()
https://docs.python.org/2/library/curses.html
función que espera la entrada de teclado para x segundos (lo que tiene que inicializar una ventana de maldiciones (WIN1) primero!
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