Я пытаюсь добавить некоторые функции в графический интерфейс, который я создал некоторое время назад, в частности, мне нужна функция текстового виджета, в которой команды терминала, которые я отправляю, показывают свой вывод.На данный момент класс перенаправителя выглядит следующим образом:
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 (команда, stdout = PIPE, stderr = STDOUT, shell = True)
и я читаю стандартный вывод через: b = a.stdout.read()
без единой проблемы (к сожалению, мне нужна эта оболочка = True, в противном случае некоторые программы, которые мне нужно вызвать, с треском проваливаются).После этого я попытался получить вывод в реальном времени для текстового виджета tkinter, поэтому я изменил b ->
while True:
b = a.stdout.readline().rstrip()
if not b:
break
print b
, но кажется, что вывод появляется только после завершения вызванного процесса, то есть простого программного обеспечения на Cкак
для (int i = 0; i <100000; i ++) {cout << i << '\ n';} </p>
будет печататься очень медленно (Я замечаю медленно, учитывая, что простая команда "ls" будет также очень медленно печатать строку за строкой) все числа в конце цикла for.Кроме того, я заметил, что графический интерфейс пользователя заморожен во время работы программ, вызываемых через подпроцесс.Есть идеи, как решить эти проблемы?
РЕДАКТИРОВАТЬ :
Я создал простой терминал, который запускает команды, используя класс многопроцессорной обработки, и 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++;
}
}
}
некоторое время ни к чему не приводит внутри текстового виджета и через некоторое время вывод появляется внезапно.Есть идеи как решить эту проблему?