我打印无限数字的程序只有在重定向sys.stdout
之后打印一些内容时才会按预期工作,否则程序会冻结,为什么会这样?这是一个错误吗?
代码:
import Tkinter as Tk
import sys
import threading
def func():
i = 0
while True:
i +=1
print i
class Std_redirector(object):
def __init__(self,widget):
self.widget = widget
def write(self,string):
self.widget.see(Tk.END)
self.widget.insert("end",string)
root = Tk.Tk()
text = Tk.Text(root)
text.pack()
sys.stdout = Std_redirector(text) #Redirect stdout to Tkinter text widget
#print 'hey' #If you uncomment this line, the program works!
thread1 = threading.Thread(target=func)
thread1.start() #Starts printing
root.mainloop()
如果您取消注释此行,则此脚本有效:print 'hey'
顺便说一下,我的操作系统是Windows 7
答案 0 :(得分:3)
我修改了这个想法,找到了两种方法让它发挥作用。
1)即使它不是线程安全的,你的方法也能正常工作。唯一的问题似乎是应用程序需要在打印到窗口小部件之前初始化。如果你想“立即”启动第二个线程,而不是从一些回调开始,这对我有用:
root.after(100, thread1.start)
2)第二个更干净的方法基于@falsetru链接的示例。但是它要求你以合理的速度打印到标准输出,这样更新就不会阻塞它。
from Tkinter import *
import threading
import Queue # This is thread safe
import time
class Std_redirector():
def __init__(self, widget):
self.widget = widget
def write(self,string):
self.widget.write(string)
class ThreadSafeText(Text):
def __init__(self, master, **options):
Text.__init__(self, master, **options)
self.queue = Queue.Queue()
self.update_me()
def write(self, line):
self.queue.put(line)
def update_me(self):
while not self.queue.empty():
line = self.queue.get_nowait()
self.insert(END, line)
self.see(END)
self.update_idletasks()
self.after(10, self.update_me)
def func():
i = 0
while True:
i += 1
print i
time.sleep(0.01)
root = Tk()
text = ThreadSafeText(root)
text.pack()
sys.stdout = Std_redirector(text)
thread1 = threading.Thread(target=func)
thread1.start()
root.mainloop()
根据我从其他GUI工具包的经验,我想使用root.after_idle()
,但它没有像我预期的那样工作。