【发布时间】:2019-08-25 07:12:32
【问题描述】:
我正在尝试向我不久前创建的 GUI 添加一些功能,特别是我需要的功能是一个文本小部件,我发送的终端命令显示它们的输出。 重定向器类现在看起来像这样:
class StdRed(object):
def __init__(self, textwid):
self.text_space = textwid
def write(self, text):
self.text_space.config(state=NORMAL)
self.text_space.insert(END,text)
self.text_space.see(END)
self.text_space.update_idletasks()
self.text_space.config(state=DISABLED)
def flush(self):
pass
确实有效。我用
替换了 os.system(...) 命令以打开终端命令a = subprocess.Popen(command, stdout=PIPE, stderr=STDOUT, shell=True)
我通过:b = a.stdout.read() 读取标准输出,没有任何问题(不幸的是,我需要 shell=True,否则我需要调用的某些程序惨遭失败)。
之后我尝试在 tkinter 文本小部件上进行实时输出,所以我更改了 b -->
while True:
b = a.stdout.readline().rstrip()
if not b:
break
print b
但似乎只有在被调用进程结束时才会出现输出,即像这样的简单C软件
for(int i = 0; i
将非常缓慢地打印(我会慢慢说,因为一个简单的“ls”命令也会非常缓慢地逐行打印)for 循环结束时的所有数字。 除此之外,我注意到 GUI 在通过子进程调用的程序运行时被冻结。关于如何解决这些问题的任何想法?
编辑:
我创建了一个简单的终端,它使用多处理类和 Popen 运行命令:
from Tkinter import *
from multiprocessing import Process, Pipe, Queue
import sys
from subprocess import PIPE, Popen, STDOUT
root = Tk()
root.title("Test Terminal")
root.resizable(False, False)
class StdRed(object):
def __init__(self, textwid):
self.text_space = textwid
def write(self, text):
self.text_space.config(state=NORMAL)
self.text_space.insert(END,text)
self.text_space.see(END)
self.text_space.update_idletasks()
self.text_space.config(state=DISABLED)
def flush(self):
pass
terminal = Frame(root, bd=2, relief=GROOVE)
terminal.grid(row=0, sticky='NSEW')
TERM = Label(terminal, text='TERMINAL', font='Helvetica 16 bold')
TERM.grid(row=0, pady=10, sticky='NSEW')
termwid = Text(terminal, height=10)
termwid.grid(row=1, sticky='NSEW')
termwid.configure(state=DISABLED, font="Helvetica 12")
sys.stdout = StdRed(termwid)
enter = StringVar()
enter.set("")
termen = Entry(terminal, textvariable=enter)
queue = Queue(maxsize=1)
a = None
def termexe(execute):
a = Popen(execute, shell=True, stdout=PIPE, stderr=STDOUT)
while True:
line = a.stdout.readline().rstrip()
if not line:
break
else:
queue.put(line)
queue.put('')
def labterm(thi):
if queue.empty():
if thi != None:
if thi.is_alive():
root.after(0,lambda:labterm(thi))
else:
pass
else:
pass
else:
q = queue.get()
print q
root.after(0,lambda:labterm(thi))
def comter(event=None, exe=None, seq=None):
global enter
if seq == 1:
if exe != None:
th = Process(target=termexe, args=(exe,))
th.daemon = True
th.start()
labterm(th)
th.join()
else:
pass
else:
if exe != None:
th = Process(target=termexe, args=(exe,))
th.daemon = True
th.start()
labterm(th)
else:
th = Process(target=termexe, args=(enter.get(),))
th.daemon = True
th.start()
enter.set('')
labterm(th)
def resetterm():
global termwid
termwid.config(state=NORMAL)
termwid.delete(1.0, END)
termwid.config(state=DISABLED)
termen.bind('<Return>', comter)
resterm = Button(terminal, text="Clear", command=resetterm)
terbut = Button(terminal, text="Command", command=comter)
termen.grid(row=2, sticky='NSEW')
terbut.grid(row=3, sticky='NSEW')
resterm.grid(row=4, sticky='NSEW')
root.mainloop()
问题是采集仍然不是实时的。 从软件中的入口运行程序:
#include <iostream>
using namespace std;
int main()
{
int i = 0;
while(1)
{
cout << i << '\n';
i++;
int a = 0;
while(a < 10E6)
{
a++;
}
}
}
在一段时间内导致文本小部件内没有任何内容,一段时间后,输出突然出现。关于如何解决这个问题的任何想法?
【问题讨论】:
标签: python user-interface tkinter subprocess python-multiprocessing