Подтвердить что ты не робот

Как установить ограничение по времени на raw_input

в python, есть ли способ, ожидая ввода пользователя, подсчитать время, чтобы после, скажем 30 секунд, функция raw_input() автоматически пропускалась?

4b9b3361

Ответ 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)