2011-11-28 171 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