it-swarm.com.de

Zeitlimit für raw_input festlegen

gibt es in Python eine Möglichkeit, beim Warten auf eine Benutzereingabe die Zeit zu zählen, so dass nach etwa 30 Sekunden die Funktion raw_input() automatisch übersprungen wird?

20
calccrypto

Die signal.alarm -Funktion, auf der die von @ jer empfohlene Lösung basiert, ist leider nur Unix. Wenn Sie eine plattformübergreifende oder Windows-spezifische Lösung benötigen, können Sie sie stattdessen auf threading.Timer stützen. Verwenden Sie thread.interrupt_main , um eine KeyboardInterrupt aus dem Timer-Thread an den Haupt-Thread zu senden. 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

dies gibt None zurück, unabhängig davon, ob die 30 Sekunden abgelaufen sind oder der Benutzer explizit entscheidet, die Tastenkombination C zu drücken, um die Eingabe von Eingaben aufzugeben. Es scheint jedoch in Ordnung, die beiden Fälle auf dieselbe Weise zu behandeln (wenn Sie unterscheiden müssen, können Sie dies verwenden.) für den Timer eine eigene Funktion, die vor dem Unterbrechen des Haupt-Threads irgendwo aufzeichnet, dass ein Timeout has aufgetreten ist, und in Ihrem Handler für KeyboardInterrupt Zugriff auf diesen "irgendwo", um zu unterscheiden, welcher der beiden Fälle vorliegt aufgetreten).

Edit: Ich hätte schwören können, dass dies funktioniert hat, aber ich muss mich geirrt haben - der Code oben lässt die offensichtlich benötigte timer.start(), und weg, selbst wenn ich damit nicht mehr arbeiten kann . select.select wäre die naheliegendste Sache, die Sie ausprobieren könnten, aber es funktioniert nicht bei einer "normalen Datei" (einschließlich stdin) in Windows - unter Unix funktioniert es bei allen Dateien, bei Windows nur bei Sockets.

Ich weiß also nicht, wie man eine plattformübergreifende "Rohdateneingabe mit Zeitüberschreitung" ausführt. Eine Windows-spezifische Abfrage kann mit einer engen Schleife msvcrt.kbhit erstellt werden, indem ein msvcrt.getche ausgeführt wird (und überprüft wird, ob es sich um eine Rückkehr handelt, die angibt, dass die Ausgabe erfolgt ist wartet weiter) und prüft bei Bedarf die Zeit bis zum Timeout. Ich kann nicht testen, weil ich keine Windows-Maschine habe (sie sind alle Macs und Linux), aber hier das ungeprüfter Codewürde ich vorschlagen:

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

Das OP in einem Kommentar sagt, dass er nicht nach Timeout return None will, aber was ist die Alternative? Ausnahme machen? Rückgabe eines anderen Standardwerts? Welche Alternative er auch haben mag, er kann ihn eindeutig anstelle meines return None ;-) einsetzen.

Wenn Sie keine Zeitüberschreitung wünschen, nur weil der Benutzer langsam eingibt (im Gegensatz zu gar nicht! -), können Sie finishat nach jeder erfolgreichen Zeicheneingabe neu berechnen.

28
Alex Martelli

Ich habe eine Lösung für dieses Problem gefunden in einem Blogbeitrag . Hier ist der Code aus diesem Blogpost:

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 ''

Bitte beachten Sie: dieser Code funktioniert nur auf * nix-Betriebssystemen .

13
jer
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

Da es selbst definiert ist ... Führen Sie es in der Befehlszeile aus. Prompt. Ich hoffe, Sie erhalten die Antwort Lesen Sie diese Datei Python-Dokument Sie werden klar sein, was gerade in diesem Code passiert ist !!

4
bilal hanif

Die Funktion input () wartet darauf, dass der Benutzer etwas eingibt (mindestens die Taste [Enter]).

Wenn Sie nicht auf die Verwendung von input () eingestellt sind, ist die Verwendung von tkinter unten viel einfacher. In tkinter können Dialogfelder (und jedes Widget) nach einer bestimmten Zeit gelöscht werden.

Hier ist ein Beispiel :

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')
3
madpentiste

Ein Fluchbeispiel, das einen zeitgesteuerten mathematischen Test erfordert

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

unter Linux könnte man Flüche und die getch-Funktion verwenden, die nicht blockiert. siehe getch ()

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

funktion, die x Sekunden lang auf die Tastatureingabe wartet (Sie müssen zuerst ein Curses-Fenster (win1) initialisieren!

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
0
Peter Fleix