在使用 EasyGUI 库接收用户输入的脚本中,如果想要在程序运行时将进度、每个操作或函数的执行结果打印到文本框中,该怎么做?
2、解决方案
虽然 EasyGUI 本身不提供这样的功能,但是可以创建一个单独的 Tkinter 窗口,使用改进版代码来将输出行显示出来。具体方法如下:
(1)导入必要的库
import sys
import thread
import subprocess
import Queue
from Tkinter import BOTH, END, Frame, Text, TOP, YES
import tkFont
(2)创建 OutputPipe 类
class OutputPipe(object):
def __init__(self, name=''):
self.lock = thread.allocate_lock()
self.name = name
def __getattr__(self, attr):
if attr == 'pipe':
command = '"%s" "%s" "%s" "%s"' % (sys.executable, __file__, os.path.basename(sys.argv[0]), self.name)
try:
self.pipe = subprocess.Popen(command, bufsize=0,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE).stdin
except Exception:
exc_type, exc_value, exc_traceback = sys.exc_info()
msg = ('%r exception in %s\n' %
(exc_type.__name__, os.path.basename(__file__)))
with open('exc_info.txt', 'wt') as info:
info.write('msg:' + msg)
traceback.print_exc(file=info)
sys.exit('fatal error occurred spawning output process')
return super(OutputPipe, self).__getattribute__(attr)
def write(self, data):
with self.lock:
self.pipe.write(data)
(3)定义队列和 Tkinter 应用程序
queue = Queue.Queue(100)
class Application(Frame):
def __init__(self, master=None, font_size=8, text_color='#0000AA', rows=25, cols=100):
Frame.__init__(self, master)
title = "Output Stream from %s" % (sys.argv[1],)
self.master.title(title)
self.pack(fill=BOTH, expand=YES)
font = tkFont.Font(family='Courier', size=font_size)
width = font.measure(' '*(cols+1))
height = font.metrics('linespace')*(rows+1)
self.configure(width=width, height=height)
self.pack_propagate(0)
self.logwidget = Text(self, font=font)
self.logwidget.pack(side=TOP, fill=BOTH, expand=YES)
self.logwidget.bind('<Key>', lambda x: 'break')
self.logwidget.bind('<Control-c>', lambda x: None)
self.logwidget.configure(foreground=text_color)
self.after(200, self.start_thread, ())
def start_thread(self, _):
thread.start_new_thread(read_stdin, (self,))
self.after(200, self.check_q, ())
def check_q(self, _):
log = self.logwidget
log_insert = log.insert
log_see = log.see
queue_get_nowait = queue.get_nowait
go = True
while go:
try:
data = queue_get_nowait()
if not data:
data = '[EOF]'
go = False
log_insert(END, data)
log_see(END)
except Queue.Empty:
self.after(200, self.check_q, ())
go = False
(4)创建 OutputPipe 对象并重定向标准输出流
sys.stderr = OutputPipe('stderr')
sys.stdout = OutputPipe('stdout')
(5)在函数中打印输出
使用 sys.stdout.write(data)
或 sys.stderr.write(data)
来打印输出。
(6)运行应用程序
在需要显示输出的脚本中,导入 errorwindow
模块并创建一个 Application 对象,然后调用 mainloop()
方法即可。
app = Application()
app.mainloop()
这样,就可以在程序运行时将进度、每个操作或函数的执行结果打印到文本框中。