2013-03-20 14 views
5

To, co chciałbym zrobić, to zadać użytkownikowi pytanie za pomocą danych wejściowych. Na przykład:Python 3 Timed Input

print('some scenario') 
prompt = input("You have 10 seconds to choose the correct answer...\n") 

i wtedy, gdy czas upłynie drukuj coś podobnego

print('Sorry, times up.') 

Każda pomoc wskazujące mnie we właściwym kierunku byłoby bardzo mile widziane.

+0

@interjay ja już przeczytać ten komentarz przed wysłaniem na moje pytanie. Przede wszystkim jestem na platformie Windows, nie Unix. Przyjęta odpowiedź mówi, że jest to tylko system Unix, i wierzę, że osoba, która odpowiedziała, powiedziała później, że nawet nie działa. Pracuję również z Pythonem 3. Potrzebuję użyć input nie raw_input. – cloud311

+3

Istnieje wiele odpowiedzi na to pytanie i na jeden opublikowany przez Francesco Frassinelli, z których wiele nie jest wyłącznie dla systemu Unix. I możesz po prostu zmienić 'raw_input' na' input'. BTW Kiedy zadajesz pytania, powinieneś podać odpowiednie informacje, takie jak uruchamianie w systemie Windows, i rozwiązania, które wypróbowałeś, ale nie działały, aby ludzie nie tracili czasu na przepisywanie starych odpowiedzi. – interjay

+1

[Wejście klawiatury z limitem czasu w języku Python] (http://stackoverflow.com/q/1335507/4279) – jfs

Odpowiedz

3

ciekawy problem, to wydaje się działać:

import time 
from threading import Thread 

answer = None 

def check(): 
    time.sleep(2) 
    if answer != None: 
     return 
    print "Too Slow" 

Thread(target = check).start() 

answer = raw_input("Input something: ") 
+3

możesz [ użyj 'threading.Timer' zamiast' Thread' + 'time.sleep'] (http://stackoverflow.com/a/15533404/4279). W Pythonie 3. nie ma 'raw_input'. – jfs

+3

Jak kończy się raw_input() w mainthread? Widzę, jak wątek check() kończy się i przesuwa "Zbyt wolno" na standardowe wyjście. Ale nie w jaki sposób raw_input() pobiera swój bufor stdin lub "wypełnia". – DevPlayer

8

Jeśli jest to dopuszczalne, aby zablokować główny wątek, gdy użytkownik nie dostarczyły odpowiedzi:

from threading import Timer 

timeout = 10 
t = Timer(timeout, print, ['Sorry, times up']) 
t.start() 
prompt = "You have %d seconds to choose the correct answer...\n" % timeout 
answer = input(prompt) 
t.cancel() 

inaczej, można użyć @Alex Martelli's answer (zmodyfikowano dla Python 3) w systemie Windows (nie testowano):

import msvcrt 
import time 

class TimeoutExpired(Exception): 
    pass 

def input_with_timeout(prompt, timeout, timer=time.monotonic): 
    sys.stdout.write(prompt) 
    sys.stdout.flush() 
    endtime = timer() + timeout 
    result = [] 
    while timer() < endtime: 
     if msvcrt.kbhit(): 
      result.append(msvcrt.getwche()) #XXX can it block on multibyte characters? 
      if result[-1] == '\n': #XXX check what Windows returns here 
       return ''.join(result[:-1]) 
     time.sleep(0.04) # just to yield to other processes/threads 
    raise TimeoutExpired 

Zastosowanie:

try: 
    answer = input_with_timeout(prompt, 10) 
except TimeoutExpired: 
    print('Sorry, times up') 
else: 
    print('Got %r' % answer) 

Na Unix można spróbować:

import select 
import sys 

def input_with_timeout(prompt, timeout): 
    sys.stdout.write(prompt) 
    sys.stdout.flush() 
    ready, _, _ = select.select([sys.stdin], [],[], timeout) 
    if ready: 
     return sys.stdin.readline().rstrip('\n') # expect stdin to be line-buffered 
    raise TimeoutExpired 

czyli

import signal 

def alarm_handler(signum, frame): 
    raise TimeoutExpired 

def input_with_timeout(prompt, timeout): 
    # set signal handler 
    signal.signal(signal.SIGALRM, alarm_handler) 
    signal.alarm(timeout) # produce SIGALRM in `timeout` seconds 

    try: 
     return input(prompt) 
    finally: 
     signal.alarm(0) # cancel alarm 
+1

Pierwsza odpowiedź została wydrukowana po przekroczeniu limitu czasu, ale dane wejściowe były nadal dostępne. –

+1

@EliezerMiron: tak, wywołanie 'input()' nie zostaje przerwane w pierwszym przykładzie, dlatego istnieje: * "Jeśli dopuszczalne jest zablokowanie głównego wątku" * przed przykładem. Jeśli chcesz przerwać wejście, użyj poniższych przykładów z 'input_with_timeout()'. – jfs

+0

Próbowałem użyć "sygnału importu", a jego wyczucie czasu wydaje się być wyłączone. Używam IDE Cloud9. Jeśli ustawię limit czasu na 0,5., Upłynie około 3 sekund, zanim upłynie limit czasu. –