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?

È stato utile?

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top