从raw_input()读取输入,而没有在Python中的其他线程覆盖的提示
-
21-09-2019 - |
题
我正在尝试使用RAW_INPUT()将用户输入命令在控制台处,这可以正常工作。问题是我有背景线程,偶尔将对数字信息输出到屏幕上,而当它们执行时,它们会弄乱输入提示(因为在当前光标恰好在任何地方,输出转移到了任何地方)。
这是一个小的Python程序,可以说明我的意思。
#!/usr/bin/env python
import threading
import time
def message_loop():
while True:
time.sleep(1)
print "Hello World"
thread = threading.Thread(target = message_loop)
thread.start()
while True:
input = raw_input("Prompt> ")
print "You typed", input
这是我运行它时的外观的一个示例:
Prompt> Hello World
Hello World
Hello World
Hello World
test
You typed test
Prompt> Hello World
Hello World
Hello World
hellHello World
o
You typed hello
Prompt> Hello World
Hello World
Hello World
Hello World
我想要的是提示与线程的输出一起移动。像这样:
Hello World
Hello World
Prompt> test
You typed test
Hello World
Hello World
Hello World
Hello World
Hello World
Prompt> hello
You typed hello
Hello World
Hello World
Hello World
Hello World
Prompt>
关于如何在不诉诸丑陋的黑客的情况下实现这一目标的任何想法? :)
解决方案
我最近遇到了这个问题,并希望在此处留下此解决方案以备将来参考。这些解决方案清除了从终端中删除的RAW_INPUT(readline)文本,打印新文本,然后重印到RAW_INPUT BUFFER中的终端。
第一个程序非常简单,但仅在只有1行文本等待RAW_INPUT时才能正常工作:
#!/usr/bin/python
import time,readline,thread,sys
def noisy_thread():
while True:
time.sleep(3)
sys.stdout.write('\r'+' '*(len(readline.get_line_buffer())+2)+'\r')
print 'Interrupting text!'
sys.stdout.write('> ' + readline.get_line_buffer())
sys.stdout.flush()
thread.start_new_thread(noisy_thread, ())
while True:
s = raw_input('> ')
输出:
$ ./threads_input.py
Interrupting text!
Interrupting text!
Interrupting text!
> WELL, PRINCE, Genoa and Lucca are now no more than private estates of the Bo
Interrupting text!
> WELL, PRINCE, Genoa and Lucca are now no more than private estates of the Bo
naparte family. No, I warn you, that if you do not tell me we are at war,
第二个正确处理2条或更多缓冲线,但是具有更多(标准)模块依赖性,并且需要一小端端子黑客:
#!/usr/bin/python
import time,readline,thread
import sys,struct,fcntl,termios
def blank_current_readline():
# Next line said to be reasonably portable for various Unixes
(rows,cols) = struct.unpack('hh', fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ,'1234'))
text_len = len(readline.get_line_buffer())+2
# ANSI escape sequences (All VT100 except ESC[0G)
sys.stdout.write('\x1b[2K') # Clear current line
sys.stdout.write('\x1b[1A\x1b[2K'*(text_len/cols)) # Move cursor up and clear line
sys.stdout.write('\x1b[0G') # Move to start of line
def noisy_thread():
while True:
time.sleep(3)
blank_current_readline()
print 'Interrupting text!'
sys.stdout.write('> ' + readline.get_line_buffer())
sys.stdout.flush() # Needed or text doesn't show until a key is pressed
if __name__ == '__main__':
thread.start_new_thread(noisy_thread, ())
while True:
s = raw_input('> ')
输出。以前的读取线路正确清除:
$ ./threads_input2.py
Interrupting text!
Interrupting text!
Interrupting text!
Interrupting text!
> WELL, PRINCE, Genoa and Lucca are now no more than private estates of the Bo
naparte family. No, I warn you, that if you do not tell me we are at war,
有用的来源:
apt类似列输出-Python库(此代码示例显示了如何获得UNIX或Windows的终端宽度)
其他提示
您需要从单个线程,而不是从多个线程更新Stdout ...否则您无法控制交错的I/O。
您将需要创建一个用于输出编写的线程。
您可以在线程中使用队列,并让所有其他线程将其输出记录信息写入其中。然后从此队列中读取并在适当的时间和提示消息一起写入stdout。
我认为这不可能。无论如何,这种行为应该如何?在用户按Enter输入之前,什么都没有出现?如果是这样,则只有在用户发出命令(或系统期望的任何内容)时,输出才会出现,并且听起来并不理想。
METHINK您的线程应输出到另一个文件。
不隶属于 StackOverflow