在固定时间内接受多个输入
Taking in multiple inputs for a fixed time
我正在使用 Python 3,我想编写一个程序,在一定时间内要求多个用户输入。这是我的尝试:
from threading import Timer
##
def timeup():
global your_time
your_time = False
return your_time
##
timeout = 5
your_Time = True
t = Timer(timeout, timeup)
t.start()
##
while your_time == True:
input()
t.cancel()
print('Stop typing!')
问题是,即使时间到了,代码仍然在等待输入。我希望循环在时间用完时准确停止。我该怎么做呢?谢谢!
这里有一个简短的方法,不使用信号,注意:While 循环将被阻塞,直到用户输入某些内容然后检查条件。
from datetime import datetime, timedelta
t = 5 # You can type for 5 seconds
def timeup():
final_time = datetime.now() + timedelta(seconds=t)
print("You can enter now for" + str(t) + " seconds")
while datetime.now() < final_time:
input()
print("STOP TYPING")
timeup()
您可以使用 poll() 方法(在 Linux 上测试):
import select,sys
def timed_input(sec):
po= select.poll() # creating a poll object
# register the standard input for polling with the file number
po.register(sys.stdin.fileno(), select.POLLIN)
while True:
# start the poll
events= po.poll(sec*1000) # timeout: milliseconds
if not events:
print("\n Sorry, it's too late...")
return ""
for fno,ev in events: # check the events and the corresponding fno
if fno == sys.stdin.fileno(): # in our case this is the only one
return(input())
s=timed_input(10)
print("From keyboard:",s)
stdin 缓冲按下的键,input() 函数立即读取该缓冲区。
此解决方案平台无关并且立即中断输入以通知现有超时。它不必等到用户按下 ENTER 键才发现发生了超时。除了及时通知用户外,这还确保在进一步处理超时后没有输入。
特征
- 平台独立(Unix / Windows)。
- 只有 StdLib,没有外部依赖。
- 只有线程,没有子进程。
- 超时立即中断。
- 提示器在超时时干净关闭。
- 在时间跨度内可以无限输入。
- 易于扩展的 PromptManager class.
- 程序可能会在超时后恢复,无需重新启动程序即可多次运行提示器实例。
这个答案使用线程管理器实例,它在
单独的提示线程和 MainThread。管理线程检查超时并将输入从提示线程转发到父线程。如果 MainThread 需要是非阻塞的(更改 _poll
以替换阻塞 queue.get()
),这种设计可以轻松修改。
超时时,管理器线程要求 ENTER 继续并使用
threading.Event
实例以确保提示线程在之前关闭
继续。请参阅特定方法的文档文本中的更多详细信息:
from threading import Thread, Event
from queue import Queue, Empty
import time
SENTINEL = object()
class PromptManager(Thread):
def __init__(self, timeout):
super().__init__()
self.timeout = timeout
self._in_queue = Queue()
self._out_queue = Queue()
self.prompter = Thread(target=self._prompter, daemon=True)
self.start_time = None
self._prompter_exit = Event() # synchronization for shutdown
self._echoed = Event() # synchronization for terminal output
def run(self):
"""Run in worker-thread. Start prompt-thread, fetch passed
inputs from in_queue and check for timeout. Forward inputs for
`_poll` in parent. If timeout occurs, enqueue SENTINEL to
break the for-loop in `_poll()`.
"""
self.start_time = time.time()
self.prompter.start()
while self.time_left > 0:
try:
txt = self._in_queue.get(timeout=self.time_left)
except Empty:
self._out_queue.put(SENTINEL)
else:
self._out_queue.put(txt)
print("\nTime is out! Press ENTER to continue.")
self._prompter_exit.wait()
@property
def time_left(self):
return self.timeout - (time.time() - self.start_time)
def start(self):
"""Start manager-thread."""
super().start()
self._poll()
def _prompter(self):
"""Prompting target function for execution in prompter-thread."""
while self.time_left > 0:
self._in_queue.put(input('>$ '))
self._echoed.wait() # prevent intermixed display
self._echoed.clear()
self._prompter_exit.set()
def _poll(self):
"""Get forwarded inputs from the manager-thread executing `run()`
and process them in the parent-thread.
"""
for msg in iter(self._out_queue.get, SENTINEL):
print(f'you typed: {msg}')
self._echoed.set()
# finalize
self._echoed.set()
self._prompter_exit.wait()
self.join()
if __name__ == '__main__':
pm = PromptManager(timeout=5)
pm.start()
示例输出:
>$ Hello
you typed: Hello
>$ Wor
Time is out! Press ENTER to continue.
Process finished with exit code 0
请注意在尝试键入 "World" 时弹出的超时消息。
我正在使用 Python 3,我想编写一个程序,在一定时间内要求多个用户输入。这是我的尝试:
from threading import Timer
##
def timeup():
global your_time
your_time = False
return your_time
##
timeout = 5
your_Time = True
t = Timer(timeout, timeup)
t.start()
##
while your_time == True:
input()
t.cancel()
print('Stop typing!')
问题是,即使时间到了,代码仍然在等待输入。我希望循环在时间用完时准确停止。我该怎么做呢?谢谢!
这里有一个简短的方法,不使用信号,注意:While 循环将被阻塞,直到用户输入某些内容然后检查条件。
from datetime import datetime, timedelta
t = 5 # You can type for 5 seconds
def timeup():
final_time = datetime.now() + timedelta(seconds=t)
print("You can enter now for" + str(t) + " seconds")
while datetime.now() < final_time:
input()
print("STOP TYPING")
timeup()
您可以使用 poll() 方法(在 Linux 上测试):
import select,sys
def timed_input(sec):
po= select.poll() # creating a poll object
# register the standard input for polling with the file number
po.register(sys.stdin.fileno(), select.POLLIN)
while True:
# start the poll
events= po.poll(sec*1000) # timeout: milliseconds
if not events:
print("\n Sorry, it's too late...")
return ""
for fno,ev in events: # check the events and the corresponding fno
if fno == sys.stdin.fileno(): # in our case this is the only one
return(input())
s=timed_input(10)
print("From keyboard:",s)
stdin 缓冲按下的键,input() 函数立即读取该缓冲区。
此解决方案平台无关并且立即中断输入以通知现有超时。它不必等到用户按下 ENTER 键才发现发生了超时。除了及时通知用户外,这还确保在进一步处理超时后没有输入。
特征
- 平台独立(Unix / Windows)。
- 只有 StdLib,没有外部依赖。
- 只有线程,没有子进程。
- 超时立即中断。
- 提示器在超时时干净关闭。
- 在时间跨度内可以无限输入。
- 易于扩展的 PromptManager class.
- 程序可能会在超时后恢复,无需重新启动程序即可多次运行提示器实例。
这个答案使用线程管理器实例,它在
单独的提示线程和 MainThread。管理线程检查超时并将输入从提示线程转发到父线程。如果 MainThread 需要是非阻塞的(更改 _poll
以替换阻塞 queue.get()
),这种设计可以轻松修改。
超时时,管理器线程要求 ENTER 继续并使用
threading.Event
实例以确保提示线程在之前关闭
继续。请参阅特定方法的文档文本中的更多详细信息:
from threading import Thread, Event
from queue import Queue, Empty
import time
SENTINEL = object()
class PromptManager(Thread):
def __init__(self, timeout):
super().__init__()
self.timeout = timeout
self._in_queue = Queue()
self._out_queue = Queue()
self.prompter = Thread(target=self._prompter, daemon=True)
self.start_time = None
self._prompter_exit = Event() # synchronization for shutdown
self._echoed = Event() # synchronization for terminal output
def run(self):
"""Run in worker-thread. Start prompt-thread, fetch passed
inputs from in_queue and check for timeout. Forward inputs for
`_poll` in parent. If timeout occurs, enqueue SENTINEL to
break the for-loop in `_poll()`.
"""
self.start_time = time.time()
self.prompter.start()
while self.time_left > 0:
try:
txt = self._in_queue.get(timeout=self.time_left)
except Empty:
self._out_queue.put(SENTINEL)
else:
self._out_queue.put(txt)
print("\nTime is out! Press ENTER to continue.")
self._prompter_exit.wait()
@property
def time_left(self):
return self.timeout - (time.time() - self.start_time)
def start(self):
"""Start manager-thread."""
super().start()
self._poll()
def _prompter(self):
"""Prompting target function for execution in prompter-thread."""
while self.time_left > 0:
self._in_queue.put(input('>$ '))
self._echoed.wait() # prevent intermixed display
self._echoed.clear()
self._prompter_exit.set()
def _poll(self):
"""Get forwarded inputs from the manager-thread executing `run()`
and process them in the parent-thread.
"""
for msg in iter(self._out_queue.get, SENTINEL):
print(f'you typed: {msg}')
self._echoed.set()
# finalize
self._echoed.set()
self._prompter_exit.wait()
self.join()
if __name__ == '__main__':
pm = PromptManager(timeout=5)
pm.start()
示例输出:
>$ Hello
you typed: Hello
>$ Wor
Time is out! Press ENTER to continue.
Process finished with exit code 0
请注意在尝试键入 "World" 时弹出的超时消息。