Pregunta

Esta pregunta ya tiene una respuesta aquí:

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?

¿Fue útil?

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top