2016-04-13 53 views
2

私は関数のstdoutをtkinterテキストウィジェットにリダイレクトしようとしています。 私が実行している問題は、すべてを1つにリストするのではなく、新しいウィンドウに各行を書き込むことです。 この関数はディレクトリをスキャンし、0kのファイルをリストします。 0kのファイルがない場合は、それを出力します。したがって、問題は、ディレクトリに30個の0kファイルがある場合、それぞれに1行の30個のウィンドウが開きます。 今、問題の内容を知っています。あなたは私の機能コードZerok()に見れば、私はそれを言っています:stdoutをtkinterテキストウィジェットにリダイレクト

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() 

答えて

1

解決方法は簡単です。複数のリダイレクタを作成しないでください。リダイレクタの全体のポイントは、一度作成すると、通常の印刷ステートメントがそのウィンドウに表示されます。

redirector機能を少し変更する必要があります。まず、Tkを呼び出すべきではありません。代わりに、tkinterプログラムはちょうど1つのルートウィンドウを持たなければならないので、Toplevelのインスタンスを作成する必要があります。第2に、書くべき正確なウィジェットを知る必要があるので、テキストウィジェットをIORedirectorに渡す必要があります。

def redirector(inputStr=""): 
    import sys 
    root = Toplevel() 
    T = Text(root) 
    sys.stdout = StdoutRedirector(T) 
    T.pack() 
    T.insert(END, inputStr) 

次に、この関数を1回だけ呼び出すようにしてください。その後、データをウィンドウに表示させるには、通常の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(): ... if os.stat (ファイル名).st_size == 0:
プリント(ファイル名)他 : プリント(「そのディレクトリに空のファイルがありません」) ブレーク

+0

ありがとうブライアン、これのほとんどは理にかなっていますが、私はいくつかの点で迷っています。 – dennis

+0

おかげさまで@Bryan Oakley、私はPythonに新しくて、さらにTkinterに新しいので、あなたの助けと忍耐を感謝します。これのほとんどは理にかなっていますが、私はいくつかの点で迷っています。まず、「テキストウィジェットをIORedirectorに渡す必要があります...」私はそこに迷っています。次に、この関数を1回呼び出すとr = redirector()です。私はそれがどのように働いていて使用されていないのですか? – dennis

+0

@Dennis:私は最初に追加することを忘れた部分を含むように私の答えを編集しました - 'write'メソッドはテキストファイルに書き込むために関数を使う必要があります。テキストウィジェットを渡す場合は、リダイレクタが何かにリダイレクトするのがポイントです。あなたはそれが何であるかを伝えなければなりません。この場合、テキストウィジェットにリダイレクトする必要があります。 –

1

上記の解決策は非常に完全です。私は基本的に1つの小さな変更だけで私のコードにコピーして貼り付けることができました。私は完全にはわかりませんなぜですが、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 

私の前に来た巨人のおかげで、この非常に明確な説明が提供されました。

関連する問題