Question

    

Cette question a déjà une réponse ici:

    
            
  •              délai d'attente sur un appel de fonction                                      14 réponses                          
  •     
    

en python, est-il un moyen de, en attendant une entrée utilisateur, compter le temps de sorte qu'après, disons 30 secondes, la fonction raw_input() est automatiquement ignorée?

Était-ce utile?

La solution

La fonction signal.alarm , sur lequel @ solution recommandée Jer est basée, est malheureusement Unix seulement. Si vous avez besoin d'une solution multi-plateforme ou spécifique à Windows, vous pouvez baser sur threading.Timer au lieu, en utilisant thread.interrupt_main pour envoyer un KeyboardInterrupt au fil conducteur du fil de minuterie. I.e.:.

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

retourne None si le 30 secondes le temps ou l'utilisateur décide explicitement de frapper le contrôle-C pour renoncer à entrer quoi que ce soit, mais il semble OK pour traiter les deux cas de la même manière (si vous avez besoin de faire la distinction, vous pouvez utiliser pour la minuterie en fonction de votre propre que, avant d'interrompre le thread principal, les dossiers quelque part le fait qu'un délai d'attente a est arrivé, et dans votre gestionnaire pour l'accès KeyboardInterrupt que « quelque part » discriminer qui des deux cas se sont présentés).

Modifier : Je aurait pu jurer ce fonctionnait, mais je devais avoir tort - le code ci-dessus passe sous silence le timer.start() évidemment nécessaire, et même avec elle que je peux « t le faire fonctionner plus. select.select serait l'évidence autre chose à essayer, mais il ne fonctionnera pas sur un « fichier normal » (y compris stdin) dans Windows -. Unix il fonctionne sur tous les fichiers, sous Windows, uniquement sur les sockets

Je ne sais pas comment faire une croix-plate-forme « entrée brute avec délai d'attente ». Une fenêtre spécifique peut être construit avec un msvcrt. kbhit , effectuer une msvcrt.getche (et vérifier si elle est un retour pour indiquer la sortie est fait, dans ce cas, il se casse de la boucle, sinon accumule et garde en attente) et vérifier le temps en temps si nécessaire. Je ne peux pas tester parce que je n'ai pas machine Windows (ils sont tous les Mac et les Linux), mais ici code non testé Je suggère:

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 dans un commentaire dit qu'il ne veut pas return None sur délai d'attente, mais quelle est l'alternative? Raising une exception? De retour une valeur par défaut différente? Quelle que soit autre qu'il veut, il peut clairement mettre en place de mon return None; -).

Si vous ne voulez pas le temps juste parce que l'utilisateur tape lentement -, vous pourriez recalcule finishat après chaque entrée de caractère avec succès <(par opposition à, non pas taper du tout!). / p>

Autres conseils

J'ai trouvé une solution à ce problème dans un blog poster . Voici le code de ce 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 ''

S'il vous plaît noter:. ce code ne de travail sur les * nix OSs

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

Comme il est auto défini ... l'exécuter en ligne de commande rapide, je l'espère, vous obtiendrez la réponse lire doc python vous être très clair ce qui vient de se passer dans ce Code !!

La fonction d'entrée () est conçu pour attendre que l'utilisateur d'entrer quelque chose (au moins la touche [Entrée]).

Si vous n'êtes pas mort mis à l'entrée d'utilisation (), ci-dessous est une solution beaucoup plus léger en utilisant tkinter. Dans tkinter, les boîtes de dialogue (et ne importe quel widget) peuvent être détruits après un certain temps.

Voici un exemple:

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 exemple maudit qui prend pour un test de mathématiques chronométré

#!/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)

sous Linux pourrait utiliser une fonction sorts et getch, son blocage non. voir getch ()

https://docs.python.org/2/library/curses.html

fonction qui attend l'entrée du clavier pendant x secondes (vous devez initialiser une fenêtre malédictions (de win1) d'abord!

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top