如何在Python3中同时进行并行输入和输出?

如何在Python3中同时进行并行输入和输出?,python,python-3.x,multithreading,shell,python-multithreading,Python,Python 3.x,Multithreading,Shell,Python Multithreading,我需要设计一个脚本,该脚本使用终端的顶部作为输出,其中一些行在无限循环中每秒钟后打印一次,而底部部分继续接受用户输入,并在上面的部分(在定期输出中)打印它们 换句话说,我需要设计一种外壳 我尝试了以下幼稚的多线程方法: #!/usr/bin/python3 from math import acos from threading import Thread from random import choice from time import sleep from queue import Qu

我需要设计一个脚本,该脚本使用终端的顶部作为输出,其中一些行在无限循环中每秒钟后打印一次,而底部部分继续接受用户输入,并在上面的部分(在定期输出中)打印它们

换句话说,我需要设计一种外壳

我尝试了以下幼稚的多线程方法:

#!/usr/bin/python3

from math import acos
from threading import Thread
from random import choice
from time import sleep
from queue import Queue, Empty

commandQueue = Queue()

def outputThreadFunc():
    outputs = ["So this is another output","Yet another output","Is this even working"] # Just for demo
    while True:
        print(choice(outputs))
        try:
            inp = commandQueue.get(timeout=0.1)
            if inp == 'exit':
                return
            else:
                print(inp)
        except Empty:
            pass        
        sleep(1)

def inputThreadFunc():
    while True:
        command = input("> ") # The shell
        if command == 'exit':
            return
        commandQueue.put(command)

# MAIN CODE
outputThread = Thread(target=outputThreadFunc)
inputThread = Thread(target=inputThreadFunc)
outputThread.start()
inputThread.start()
outputThread.join()
inputThread.join()

print("Exit")
但很明显,正如预期的那样,当用户不断键入时,输出行与输入行合并


有什么想法吗?

最简单的解决方案是使用两个脚本;一个是打印输出的服务器,另一个是向服务器发送用户输入的客户端。然后,您可以使用标准解决方案,如
tmux
在两个窗格中打开这两个脚本。

如注释中所述,使用
诅咒库

更新 输入和输出使用两个子温

#/usr/bin/python3
进口诅咒
从数学导入acos
从线程导入线程
从随机进口选择
从时间上导入睡眠
从队列导入队列,为空
commandQueue=Queue()
stdscr=curses.initscr()
stdscr.键盘(正确)
upperwin=stdscr.subwin(2,80,0,0)
lowerwin=stdscr.subwin(2,0)
def outputThreadFunc():
outputs=[“这是另一个输出”,“又是另一个输出”,“这是否有效”]#仅用于演示
尽管如此:
upperwin.clear()
addstr(f“{choice(outputs)}”)
尝试:
inp=commandQueue.get(超时=0.1)
如果inp==“退出”:
返回
其他:
upperwin.addch(“\n”)
upperwin.addstr(inp)
除空外:
通过
upperwin.refresh()
睡眠(1)
def inputThreadFunc():
尽管如此:
全局缓冲区
lowerwin.addstr(“->”)
command=lowerwin.getstr()
如果命令:
命令=命令解码(“utf-8”)
commandQueue.put(命令)
lowerwin.clear()
lowerwin.refresh()
如果命令==‘退出’:
返回
#主代码
outputThread=Thread(目标=outputThreadFunc)
inputThread=Thread(目标=inputThreadFunc)
outputThread.start()
inputThread.start()
outputThread.join()
inputThread.join()
stdscr.键盘(错误)
诅咒
打印(“退出”)
老办法 我编辑了您的示例,使用
getch
代替
input

#/usr/bin/python3
进口诅咒
导入日期时间
从数学导入acos
从线程导入线程
从随机进口选择
从时间上导入睡眠
从队列导入队列,为空
信息刷新秒数=1
commandQueue=Queue()
buffer=list()#存储输入缓冲区
stdscr=curses.initscr()
stdscr.键盘(正确)
def outputThreadFunc():
outputs=[“这是另一个输出”,“又是另一个输出”,“这是否有效”]#仅用于演示
info=choice(outputs),datetime.datetime.now()
尽管如此:
如果datetime.datetime.now()-info[1]>datetime.timedelta(秒=信息刷新秒):
#一定时间后刷新信息
info=choice(outputs),datetime.datetime.now()#更新信息的时间戳
inp=''
缓冲区\文本=''。连接(缓冲区)
尝试:
command=commandQueue.get(超时=0.1)
如果命令==‘退出’:
返回
inp=f“\n{command}”
除空外:
通过
output_string=f“{info[0]}{inp}\n->{buffer_text}”
stdscr.clear()
stdscr.addstr(输出字符串)
stdscr.refresh()
如果是inp:
#以确保看到该命令
睡眠(1)
def inputThreadFunc():
尽管如此:
全局缓冲区
#一次获取一个字符
key=stdscr.getch()
诅咒
如果chr(key)='\n':
command=''.join(缓冲区)
commandQueue.put(命令)
如果命令==‘退出’:
返回
缓冲区=[]
elif key==curses.key\u退格:
如果缓冲区:
buffer.pop()
其他:
buffer.append(chr(key))
#主代码
outputThread=Thread(目标=outputThreadFunc)
inputThread=Thread(目标=inputThreadFunc)
outputThread.start()
inputThread.start()
outputThread.join()
inputThread.join()
stdscr.键盘(错误)
诅咒
打印(“退出”)

由于终端写入输出的方式,两者正在合并。它在缓冲区中收集输出,当时间合适时,它会立即输出所有内容。一个简单的解决方法是在每个实际语句之前使用
'\n'
,这样每个新输出都位于单独的行上

#/usr/bin/python3
.
.
.
如果inp==“退出”:
返回
其他:
打印(“\n”,inp)#在这里更改
.
.
.
命令=输入(“\n>”)#在这里更改
如果命令==‘退出’:
返回
.
.
.
打印(“退出”)

请注意,由于两个线程并行运行,下一个输出将在您完成键入并按enter键输入之前打印(除非您可以非常快速地键入并具有非常快速的反射)。希望这能回答你的问题

使用tkinter设计您的UI-底部输入,顶部输出。是否回答了您的问题?或者:,,,,,,,,,
有什么想法吗?
-似乎这个问题没有最好的答案。ncurses如何?允许吗?我如何修改它,使我选择的随机行不会在每次循环后被删除,并且不完整的输入字符串不会与之混淆?@CaptainWoof我已经更新了答案。有时间戳、信息和变量