バックグラウンドでコマンド実行ハマリ

pygtkで、GUIを作ってるが、以下のハマリで、
一日つぶれた。

その1 popenのバッファリング

popenで、コマンドを実行し、コマンドの出力を読み込んで、
ウィンドウなどに表示する時
デフォルトだと、コマンドの実行が終了するまで、結果が表示されない。
原因は、popenのI/Oのバッファリング。
解決するには、
#/usr/bin/python -n
と「-n」オプションをつける。海外のMLで発見。

その2

  • やりたいこと:
    • 1) ウィンドウAから、「設定反映ボタン」を押すと、seedit-loadコマンドを呼び出して、設定反映
    • 2) 設定反映作業中(結構時間がかかることも)は、ModalなダイアログBが出てくる
    • 3) 設定反映作業が終わると、ダイアログBが閉じる
  • 遭遇したハマリ
    • ウィンドウAの設定反映押下時のコールバックで
      • Dialogを作成、dialog.show_all()
      • Threadを開いて、seeedit-loadを実行(thread.start()
      • で、dialog.run()で、ダイアログのループ

これをやると、なぜか、
dialog.run -> ダイアログを自分で閉じる-> dialog.runが帰ってくる -> thread.start
の順番で実行されてしまい、ハマリまくった。
どうやら、gtkは、内部でthreadの制御をやってるようだ??
ダイアログが表示されるタイミングが謎である。

以下の流れにしたら動いた。

    • ウィンドウA設定反映ボタン押下時のコールバックで
      • Dialogを作成、dialog.show_all, dialog.runまでやってしまう
      • Dialogの、"show"シグナルハンドラを作る
      • showシグナルハンドラの中で、設定反映スレッドを実行

こうすると、ダイアログが表示された後で、スレッドが実行されることが保証される。

その3

上が動いた状態で。。

  • ウィンドウA設定反映ボタン押下
  • ダイアログB開く、スレッドが走る
  • スレッドの中で、ウィンドウAのラベルの値を変える

というプログラムもうまく動かず。動くとき、動かない時がある。ウィンドウが真っ白になったり。
これはあきらめる。

その4

設定反映スレッドの中で、ダイアログBのTextBufferに、設定反映コマンドの出力を表示しようとしたが、、
設定反映コマンドの出力がでかすぎると、親のウィンドウAごとお亡くなりになることがある。
再現しない。
→ これも、設定反映コマンドの出力表示はあきらめ。標準出力にとりあえず出しとく。


その3、その4はXULだと、簡単に動いたのだがなぁ。
pygtkは使いやすいが、中の人であるgtkでは
おそらく抽象化があまりされておらず、
生のXのAPIに近いことをやっていることを推測。

にしても、GUIプログラミングは、難しいなぁ(汗