Таймер на выбор действия
Скажу сразу, у меня Windows 10 и Python 3.9, если эта информация вдруг понадобится.
Я никогда не сталкивалась с подобной задачей и использованием времени в программе, потому будет очень здорово, если на вопрос будет ответ, который можно будет доступно понять.
Мне хотелось бы, чтобы было установлено опрелённое время, которое довалось бы человеку на выбор нужного варианта ответа. Но. Нужен таймер, который в режиме реального времени будет отсчитывать время, чтобы человек мог его контролировать (максимум 10 секунд).
f = None
while f not in ['1' , '2']:
f = input ("""Хотите взять предмет с собой?
1. Да.
2. Нет. """)
if f == '1':
print ("Хороший выбор.")
elif f == '2':
print ("Очень зря.")
else:
print ("Такого варианта ответа нет,ответьте на вопрос ещё раз.")
Ответы (2 шт):
Если под Windows, то можно привлечь msvcrt читать посимвольно в отдельном потоке. Хотя... В данном случае тут потоки даже не нужны.
import msvcrt, sys, time
def timed_input(text, string_mode=True, default=None, timeout=5):
def flushed_output(out_text):
sys.stdout.write(out_text)
sys.stdout.flush()
flushed_output(text)
result = default
input_text = ""
if not string_mode:
last_timeout = timeout
time_text = str(timeout)
time_text_len = len(time_text)
flushed_output(f"[{time_text:>{time_text_len}}] ")
time_start = time.time()
while True:
if msvcrt.kbhit():
chr = msvcrt.getwch()
flushed_output(chr)
if string_mode:
if ord(chr) == 13:
break
input_text += chr
else:
input_text = chr
break
time.sleep(0.05)
dt = int(time.time() - time_start)
if not string_mode:
if timeout - dt < last_timeout:
last_timeout = timeout - dt
flushed_output("\b"*(time_text_len+3)+f"[{last_timeout:>{time_text_len}}] ")
if dt >= timeout:
break
if len(input_text) > 0:
result = input_text
flushed_output("\n")
return result
name = timed_input("Введите ваше имя за 5 секунд: ", default="Иванушка-дурачок", timeout=5)
print("Добро пожаловать,", name)
f = None
while f not in ['1' , '2']:
f = timed_input ("""Хотите взять предмет с собой?
1. Да.
2. Нет.
Ваш выбор? """, string_mode=False, timeout=10)
if f == '1':
print ("Хороший выбор.")
elif f == '2':
print ("Очень зря.")
elif not f:
print ("Вы так и не определились, попробуйте снова.")
else:
print ("Такого варианта ответа нет, ответьте на вопрос ещё раз.")
А вот коротко, кроссплатфоменно, без внешних библиотек:
import threading
import signal
class Timeout(threading.Thread):
def __init__(self, timeout):
self.timeout = timeout
self.done = threading.Lock()
self.main_id = threading.get_ident()
super().__init__()
def run(self):
ok = self.done.acquire(blocking=True, timeout=self.timeout)
if not ok:
signal.pthread_kill(self.main_id, signal.SIGINT)
def __enter__(self):
self.done.acquire()
self.start()
return self
def __exit__(self, type, value, traceback):
self.done.release()
return True
with Timeout(2):
try:
input('введите за 2 сек:')
except KeyboardInterrupt:
print('не успел')
else:
print('успел')
Тут таймаут вынесен в контекст менеджер, чтоб основной код не засорять. pthread_kill наверное единственный метод прервать стандартный input() - кто знает другие?