Python / Tkinter:循环迭代未完成

时间:2011-11-28 10:12:53

标签: python loops textbox tkinter subprocess

在下面的例子中,我试图将temp2脚本的所有输出(通过子进程运行)打印到文本框小部件上。

我面临的问题是,在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 

3 个答案:

答案 0 :(得分:1)

你的问题是对test.stdout.readline的调用是阻塞的 - 这意味着处理将在那里停止,只有当有新的数据可用时才会恢复。

test.stderr.readline当然也是如此。

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

(有关文件系统的文件,您可以使用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()

答案 1 :(得分: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()

答案 2 :(得分:0)

正如jsbueno回答的那样,问题来自阻止对readline的呼叫。您可以使用文件事件源来获取数据可用时的通知(通过createfilehandler tkinter方法)。有关详细信息,请参阅this previous answer

相关问题