в python, есть ли способ, ожидая ввода пользователя, подсчитать время, чтобы после, скажем 30 секунд, функция raw_input()
автоматически пропускалась?
Как установить ограничение по времени на raw_input
Ответ 1
Функция signal.alarm, на которой основано рекомендуемое решение @jer, к сожалению, относится только к Unix. Если вам требуется кросс-платформенное решение или решение для Windows, вы можете использовать его threading.Timer, используя thread.interrupt_main, чтобы отправить KeyboardInterrupt
в основной поток из потока таймера. То есть:.
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
это вернет None, не истекает ли 30-секундный тайм-аут, или пользователь явно решает поразить элемент управления-C, чтобы отказаться от ввода чего-либо, но, похоже, нормально обрабатывать два случая одинаково (если вам нужно различать, вы можете использовать для таймера собственную функцию, которая перед прерыванием основного потока записывает где-то тот факт, что тайм-аут произошел, и в вашем обработчике для KeyboardInterrupt
доступа, который "где-то", чтобы различать, какой из двух случаев произошел).
Изменить. Я мог бы поклясться, что это работает, но я, должно быть, ошибся. В приведенном выше коде отсутствует явно необходимый timer.start()
, и даже с ним я не могу заставить его работать больше. select.select
было бы очевидным, что бы попробовать, но он не будет работать на "нормальном файле" (включая stdin) в Windows - в Unix он работает со всеми файлами в Windows, только в сокетах.
Поэтому я не знаю, как сделать кросс-платформенный "сырой ввод с таймаутом". Специфично для окна можно построить с помощью опроса msvcrt.kbhit, выполняющего msvcrt.getche
(и проверяя, является ли это возвратом для указания выходной результат, и в этом случае он выходит из цикла, иначе накапливается и продолжает ждать) и время от времени проверяет время ожидания. Я не могу протестировать, потому что у меня нет машины Windows (все они Mac и Linux), но здесь непроверенный код я бы предложил:
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
ОП в комментарии говорит, что он не хочет return None
после таймаута, но какая альтернатива? Создание исключения? Возврат другого значения по умолчанию? Какую бы альтернативу он ни пожелал, он может четко помещать его вместо моего return None
; -).
Если вы не хотите тайм-аут только потому, что пользователь печатает медленно (в отличие от, а не набрав вообще!), вы можете перекомпоновать финал после каждого успешного ввода символа.
Ответ 2
Я нашел решение этой проблемы в сообщении в блоге. Вот код из этого сообщения в блоге:
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 ''
Обратите внимание: этот код будет работать только в ОС * nix.
Ответ 3
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
Как он сам определяется... запустите его в командной строке, надеюсь, вы получите ответ прочитайте это python doc, вы будете совершенно ясно, что только что произошло в этом коде!
Ответ 4
Функция input() предназначена для ожидания ввода пользователем чего-либо (по крайней мере, клавиши [Enter]).
Если вы не настроены на использование ввода(), ниже это гораздо более легкое решение, использующее tkinter. В tkinter диалоговые окна (и любой виджет) могут быть уничтожены по истечении заданного времени.
Вот пример:
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')
Ответ 5
под linux можно использовать проклятия и функцию getch, не блокируя их. см. getch()
https://docs.python.org/2/library/curses.html
которая ожидает ввода клавиатуры в течение x секунд (сначала необходимо инициализировать окно проклятия (win1)!
def tastaturabfrage():
einstiegszeit=int(time.time()) #get time now
wartezeit=2.00 #time to wait in seconds
while einstiegszeit+wartezeit>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
return
Ответ 6
Пример проклятий, который берет для математического теста с течением времени
#!/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)