Wie Frist auf raw_input auf [Duplikat]
-
05-10-2019 - |
Frage
Diese Frage bereits eine Antwort hier:
- Timeout auf einen Funktionsaufruf 14 Antworten
in Python, ist es eine Möglichkeit zu, während für eine Benutzereingabe wartet, zählen Zeit, so dass nach dem, sagen wir 30 Sekunden wird die raw_input()
Funktion automatisch übersprungen?
Lösung
Die signal.alarm Funktion, auf dem @ jer empfohlenen Lösung basiert, ist leider Unix-only. Wenn Sie eine plattformübergreifende oder Windows-spezifische Lösung benötigen, können Sie es auf Basis threading.Timer stattdessen mit thread.interrupt_main eine KeyboardInterrupt
an den Haupt-Thread aus dem Zeitgeber-Thread zu senden. Das heißt:.
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 wird return None, ob die 30 Sekunden Zeit oder der Benutzer entscheidet, explizit auf die Treffersteuer-C bei der Eingabe auf nichts zu verzichten, aber es scheint OK, um die beiden Fälle in gleicher Weise zu behandeln (wenn Sie brauchen, um zu unterscheiden, Sie könnten für die Timer-Funktion Ihrer eigenen verwenden, die vor dem Haupt-Thread, Aufzeichnungen irgendwo die Tatsache zu unterbrechen, dass ein Timeout hat passiert ist, und in Ihrem Handler für KeyboardInterrupt
Zugriff dass „irgendwo“ zu unterscheiden, die die beiden Fälle aufgetreten ist).
Bearbeiten : Ich diese Arbeit war hätte schwören können, aber ich muss falsch gewesen - der Code oben lässt die offensichtlich notwendige timer.start()
, und auch damit kann ich ‚t macht es nicht mehr arbeiten. select.select
wäre die offensichtliche andere Sache, um zu versuchen, aber es wird nicht die Arbeit an einer „normalen Datei“ (einschließlich stdin) in Windows -. in Unix für alle Dateien arbeitet, in Windows, nur an Steckdosen
Also ich weiß nicht, wie eine Cross-Plattform „raw Eingang mit timeout“ zu tun. Ein Windows-spezifisch man kann mit einem engen Schleife Polling msvcrt konstruiert werden. kbhit , Durchführen einer msvcrt.getche
(und prüfen, ob es sich um eine Rückkehr ist die Ausgabe, um anzuzeigen, fertig ist, in diesem Fall ist es der Schleife ausbricht, sammelt sich sonst und hält zu warten) und die Zeit zu Zeit überprüft, wenn nötig. Ich kann nicht testen, weil ich keinen Windows-Rechner haben (sie sind alle Macs und Linux sind), aber hier die ungetesteten Code Ich würde 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
Die OP in einem Kommentar, sagt er nicht zu return None
auf Timeout will, aber was ist die Alternative? Die Anhebung eine Ausnahme? Rückgabe eines anderen Standardwert? Was auch immer er will Alternative er es klar anstelle meines return None
setzen kann; -).
Wenn Sie nicht möchten, dass zu der Zeit nur, weil der Benutzer der Eingabe langsam (im Gegensatz zu, Schreiben nicht an alle! -), könnten Sie finishat nach jeder erfolgreichen Zeicheneingabe neu berechnen <. / p>
Andere Tipps
fand ich eine Lösung für dieses Problem in einem Blog Post . Hier ist der Code aus dieser Blog-Post:
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 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
Wie es sich von selbst definiert ist ... führen Sie es in Befehlszeile, ich hoffe, Sie die Antwort bekommen Lesen Sie diese Python doc Kristall wird klar sein, was in dieser gerade passiert Code !!
Der Eingang () Funktion ist für den Benutzer warten, etwas zu geben (zumindest die [Enter] -Taste).
Wenn Sie nicht tot Set Verwendung Eingang () sind, ist unten eine viel leichtere Lösung tkinter verwenden. In tkinter können Dialogfelder (und jedes Widget) nach einer bestimmten Zeit zerstört 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')
Ein Fluch Beispiel, die für einen zeitlich Mathe-Test nimmt
#!/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)
unter Linux könnte man Flüche und getch Funktion, seine nicht blockierende verwenden. siehe getch ()
https://docs.python.org/2/library/curses.html
Funktion, die darauf wartet, Tastatureingabe für x Sekunden (Sie müssen zuerst eine Flüche Fenster (win1) initialisiert werden!
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