我正在尝试将函数的stdout重定向到tkinter文本小部件。
我遇到的问题是它将每一行写入一个新窗口,而不是将所有内容都列在一个窗口中。
该函数扫描目录并列出任何0k的文件。如果没有0k的文件则打印出来。所以,问题是如果一个目录中有30个0k文件,它将打开30个窗口,每个窗口中只有一行。
现在,我知道问题是什么。如果您查看我的功能代码Zerok()
,我告诉它:
if os.stat(filename).st_size==0:
redirector(filename)
我知道每次os.stat看到一个0k的文件然后将它发送到重定向器,这就是为什么它为每个文件的新窗口。 我根本不知道如何解决它。 完整的代码如下。 谢谢你的帮助。
import Tkinter
from Tkinter import *
import tkFileDialog
class IORedirector(object):
'''A general class for redirecting I/O to this Text widget.'''
def __init__(self,text_area):
self.text_area = text_area
class StdoutRedirector(IORedirector):
'''A class for redirecting stdout to this Text widget.'''
def write(self,str):
self.text_area.write(str,False)
def redirector(inputStr):
import sys
root = Tk()
sys.stdout = StdoutRedirector(root)
T = Text(root)
T.pack()
T.insert(END, inputStr)
####This Function checks a User defined directory for 0k files
def Zerok():
import os
sys.stdout.write = redirector #whenever sys.stdout.write is called, redirector is called.
PATH = tkFileDialog.askdirectory(initialdir="/",title='Please select a directory')
for root,dirs,files in os.walk(PATH):
for name in files:
filename=os.path.join(root,name)
if os.stat(filename).st_size==0:
redirector(filename)
else:
redirector("There are no empty files in that Directory")
break
#############################Main GUI Window###########################
win = Tk()
f = Frame(win)
b1 = Button(f,text="List Size")
b2 = Button(f,text="ZeroK")
b3 = Button(f,text="Rename")
b4 = Button(f,text="ListGen")
b5 = Button(f,text="ListDir")
b1.pack()
b2.pack()
b3.pack()
b4.pack()
b5.pack()
l = Label(win, text="Select an Option")
l.pack()
f.pack()
b2.configure(command=Zerok)
win.mainloop()
答案 0 :(得分:2)
修复很简单:不要创建多个重定向器。重定向器的重点是您创建一次,然后普通的打印语句将显示在该窗口中。
您需要对redirector
功能进行一些小的更改。首先,它不应该调用Tk
;相反,它应该创建一个Toplevel
的实例,因为tkinter程序必须只有一个根窗口。其次,您必须将文本小部件传递给IORedirector
,因为它需要知道要写入的确切小部件。
def redirector(inputStr=""):
import sys
root = Toplevel()
T = Text(root)
sys.stdout = StdoutRedirector(T)
T.pack()
T.insert(END, inputStr)
接下来,您应该只调用此功能一次。从那时起,要在窗口中显示数据,您将使用正常的print
语句。
您可以在主代码块中创建它:
win = Tk()
...
r = redirector()
win.mainloop()
接下来,您需要修改write
函数,因为它必须写入文本小部件:
class StdoutRedirector(IORedirector):
'''A class for redirecting stdout to this Text widget.'''
def write(self,str):
self.text_area.insert("end", str)
最后,将Zerok
函数更改为使用print语句:
def Zerok():
...
如果os.stat(filename).st_size == 0:
打印(文件名)
其他:
print(“该目录中没有空文件”)
破
答案 1 :(得分:2)
上述解决方案非常完善;我只能通过一个小的修改就可以将它复制并粘贴到我的代码中。我不完全确定为什么,但StdoutRedirector
需要刷新方法。
我猜它是因为sys.stdout
在退出时会调用flush()
方法,但我还没有深入到文档中实际上明白这意味着什么。
在Jupyter环境中运行上述代码会导致代码无限期挂起,直到内核重新启动。控制台发出以下错误:
sys.stdout.flush()
AttributeError: 'StdoutRedirector' object has no attribute 'flush'
ERROR:tornado.general:Uncaught exception, closing connection.
简单的解决方案是通过添加flush方法对StdoutRedirector
类进行小的更改。
class StdoutRedirector(IORedirector):
'''A class for redirecting stdout to this Text widget.'''
def write(self,str):
self.text_area.insert("end", str)
def flush(self):
pass
感谢摆在我面前的巨人,并提供了非常明确的解释。