wxPython で標準出力を text control に表示する

最初、子プロセスを生成してー、とか難しく考えていたのですが、Python では

  • 標準入出力がオブジェクトであり、
  • wx.Frame (フレーム)も同様にオブジェクトである。また、
  • クラスの親子(継承)関係が非常に柔軟である、

という特徴のため、これを非常に簡単に実現できることが分かりました。つまり、フレームに write() と flush() のメソッドを実装するだけで、こいつをストリームのように扱うことができるわけです。実にエレガントな仕様です。
というわけで、ちょっとサンプルコードを書いてみました。知っている人には当たり前のことだと思うんですが、乞う御容赦。

import wx

class TopFrame(wx.Frame):
    def __init__(self, parent, ID, name):
        wx.Frame.__init__(self, parent, ID, name)
        self.t1 = wx.TextCtrl(self, -1, value="Hello.\n",
            style=wx.TE_MULTILINE | wx.TE_READONLY)

        import sys
        sys.stdout = sys.stderr = self

        print "This is stdout buffer."
        sys.stderr.write("This is also stderr.\n")
        self.Show()

    def write(self, msg):
        self.t1.AppendText(msg)

    def flush(self):
        pass

class MyApp(wx.App):
    def OnInit(self):
        f = TopFrame(None, -1, "Stdout App")
        f.Show(True)
        self.SetTopWindow(f)
        return True

if __name__ == '__main__':
    a = MyApp()
    a.MainLoop()

ちなみに、私が GUI のコードを書いているなんて、実に希有なことなのです。基本的に、GUI って嫌いだし、GUI のコーディングもとても面倒。wxWidgets ばんざい。