Python:中断内置input()以设置新的提示(在用户输入之前)

问题描述 投票:0回答:1

我有一个具有连续循环的函数,要求用户使用python的内置输入(提示)输入输入。我也有一个单独的线程来做一些工作,并且当该线程中满足某个条件时,输入提示应会更改。

因此,在启动时说提示是“输入:”,但是在线程工作的中间,条件已得到满足,因此提示应切换为“继续前进,键入:”。现在,如果用户没有在该第一个提示处输入任何内容,但是线程到达了切换提示的位置,那么我们仍然停留在第一个阻塞的输入调用上,该调用的提示符为“ Input:”。

# Start the thread that does some work and eventually changes the prompt
myThread.start()

#Start looping to ask for user input, get the prompt from the thread
while True:
    userInput = input(myThread.get_prompt())
    <do something with input>

我知道我可以在执行stdin.readline()之前通过select([stdin],[],[],0.0)来轮询stdin,然后如果1)得到用户输入或2则再次打印提示),如果提示更改。

但是,我想找到一个使用Python内置的input()函数的解决方案,以便可以使用python的readline模块设置制表符完成。

我尝试播放一个基本上每隔几秒钟就会中断input()的信号。与此相关的是,我需要使新的input()调用变得无缝,而无需重新打印提示。像这样:

myThread.start()

while True:
   userInput = None
   signal(SIGALRM, handler)
   signal.alarm(3)
   try:
      userInput = input("\r" + myThread.get_prompt())
   except TimeoutError:
      pass
   finally:
      signal.alarm(0)  
   <do something with input>

def handler(signum, frame):
    raise TimeoutError

这是一团糟,但是当它超时并调用新的input()时,将打印当前的行缓冲区,但光标位于它的前面。因此,如果我键入“ aaa”,那么它将重新打印“ aaa”,但光标不在该缓冲区的末尾,而是在缓冲区的开始。

有什么建议吗?

更新:我当然可以尝试使用Signal选项玩更多游戏。到目前为止,这似乎是我最好的选择。如果用户已经开始输入内容,我似乎只是无法使光标移动到输入缓冲区的末尾。我不想让用户知道呼叫超时并再次被呼叫。

python input command-prompt stdin python-multithreading
1个回答
0
投票

好吧,我知道了。它比使用信号警报超时更好。

如果将来有人遇到这个特定问题,本质上就是我所做的:

import threading
import time
import readline
import sys

class MyThread(threading.Thread):
    def __init__(self):
        super(MyThread, self).__init__()
        # Set the initial prompt
        self.prompt = "Input: "

    def run(self):
        time.sleep(6)
        # Now we want to change the prompt so that next time input loop asks for prompt it is correct
        self.set_prompt("Go ahead, type: ")

        # Now overwrite what was there in the prompt
        sys.stdout.write("\r" + self.get_prompt())
        sys.stdout.flush()

        # Get the current line buffer and reprint it, in case some input had started to be entered when the prompt was switched
        sys.stdout.write(readline.get_line_buffer())
        sys.stdout.flush()

    def get_prompt(self):
        return self.prompt

    def set_prompt(self, new_prompt):
        self.prompt = new_prompt


# Create and start thread
myThread = MyThread()
myThread.start()

# Input loop
while True:
    userInput = input(myThread.get_prompt())
    print("Got: " + userInput)

[如果您使用的是制表符完成(我在这里没有显示),您可能会注意到,如果您在第一次切换提示后尝试制表符完成(不接受来自第一个提示的任何输入),那么制表符就会完成仍然认为我们正在从第一个提示中读取内容,因此将重印该提示。在这种情况下,您需要执行以下操作:

readline.set_completion_display_matches_hook(display)

其中display是一个函数,其功能类似于我们的线程必须重写正确的提示:

def display(substitution, matches, longest_match_length):
    # Print the matches
    print('')
    buffer = ''
    for match in matches:
        buffer += match + "     "
    print(buffer)
    # Rewrite the NEW prompt
    sys.stdout.write(<prompt>)
    sys.stdout.flush()
    sys.stdout.write(readline.get_line_buffer())
    sys.stdout.flush()
© www.soinside.com 2019 - 2024. All rights reserved.