2011-11-28 117 views
0

在以下情况下,我试图将temp2脚本(通过子进程运行)的所有输出实时打印到文本框小部件上。Python/Tkinter:循环迭代没有完成

我面临的问题是这个,在temp2中,对于i <= 468,脚本工作正常,对我来说它似乎是实时的。

但是,如果我把i = 469或以上,执行停止许多迭代后没有完成。

因此,例如,对于i = 469,日志文件的条目为i = 469i = 3。整个过程停止后。

请注意:i = 469可能与您的机器不同。如果i = 469适合您,请尝试更高的价值。

Temp1.py是主要脚本。

#temp1.py 
from Tkinter import * 
import Tkinter as tk 
import os 
import ttk 
os.system('echo OS ready') 
os.system('chmod 755 *') 
import subprocess 
import sys 

#Creating new Window to display output 
t = Tk() 
t.title('output Run Display') 
t.geometry('800x1000-5+40') 
t.state('normal') 
little = Label(t, text="NRUNTEST OUTPUT LOG").grid(column = 0, row = 0) 
log = Text(t, state='disabled', width=115, height=150, wrap='none') 
log.grid(row = 1, column = 0) 

test=subprocess.Popen('temp2',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) 


#stdout 
while True: 
    line_out = test.stdout.readline() 
    line_er = test.stderr.readline() 
    if line_out == "" and line_er == "": 
     break 
    else: 
     log['state'] = 'normal' 
     log.insert('end', line_out) 
     log.insert('end', line_er) 
     log['state'] = 'disabled' 
     print line_out 
     print line_er 
     t.update() 
t.mainloop() 

下面是我通过子过程运行的脚本。

#temp2 #csh script 

set i = 469 
while ($i > 0) 
    echo i is $i | tee -a log 
    set i = `expr "$i" - 1` 
end 
+1

是否正确缩进了“else:”行?此外,下面的行似乎无效... – eumiro

+0

在我的翻译器里没问题,在这里纠正了由于从unix复制粘贴到窗口机器造成的一些缩进错误 – Ani

回答

0
import os 
import ConfigParser 
from Tkinter import * 
import Tkinter as tk 
import os 
import ttk 
os.system('echo OS ready') 
os.system('chmod 755 *') 
import subprocess 
from subprocess import call 
import sys 

os.system('rm stdout') 

#Creating new Window to display output 
t = Tk() 
t.title('output Run Display') 
t.geometry('100x100') 
t.state('normal') 
little = Label(t, text="NRUNTEST OUTPUT LOG").grid(column = 0, row = 0) 
log = Text(t, state='disabled', width=50, height=50, wrap='none') 
log.grid(row = 1, column = 0,sticky=(N,W,E,S)) 
s = ttk.Scrollbar(t,orient=VERTICAL,command=log.yview) 
s.grid(column=1,row=1,sticky=(N,S)) 
log.configure(yscrollcommand=s.set) 
ttk.Sizegrip().grid(column=1, row=1, sticky=(S,E)) 

with open("stdout","wb") as out: 
    with open("stderr","wb") as err: 
     test=subprocess.Popen('tem',shell=True,stdout=out,stderr=err) 
fout = open('stdout','r') 
ferr = open('stderr','r') 
def verify(): 

    data_out = fout.readlines() 
    data_out = ''.join(data_out) 

    log['state'] = 'normal' 
    log.insert('end',data_out) 
    log['state'] = 'disabled' 
    #print data_out 

    t.after(1000,verify) 
    fout.close() 

verify() 

t.mainloop() 
1

你的问题是,调用test.stdout.readline阻止 - 这意味着处理将停在那里,当有数据avalilable的新线,只返回恢复。当然,test.stderr.readline也是如此。

我认为处理你想要的最简单的方法是让你的子进程写入文件系统上的一个文件,在主进程中打开该文件,并尝试在定期调用的tkinter回调函数中读取它tkinter方法的.after

(戕上的文件系统,你可以使用seektell方法来检查,如果你是在文件的最后文件)

注意,在你的代码放在为例,你要Tkinter.mainloop通话只达到已经完成了子流程之后。

更好的解决方案是在不依赖shell脚本的情况下完全读取您想要的Python日志。

Tkinter.after与javascript的settimeout类似 - 它是一个小部件(比如说你的“t”对象)的一个方法,并且传递它等待的毫秒数,以及要调用的函数的名称 -

def verify_output(): 
    # read subprocess output file and update the window if needed 
    ... 
    # call self after 1 second 
    t.after(1000, verify_output) 

# callreader callback for the first time: 

t.after(10, verify_output) 
Tkinter.mainloop() 
+0

谢谢。你的建议有帮助。 – Ani

0

由于jsbueno答案,你的问题来自阻塞调用readline。当数据可用时,您可以使用文件事件源来获得通知(通过createfilehandler tkinter方法)。详情请参阅this previous answer