バックグラウンドでコマンド実行ハマリ
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()で、ダイアログのループ
- ウィンドウAの設定反映押下時のコールバックで
これをやると、なぜか、
dialog.run -> ダイアログを自分で閉じる-> dialog.runが帰ってくる -> thread.start
の順番で実行されてしまい、ハマリまくった。
どうやら、gtkは、内部でthreadの制御をやってるようだ??
ダイアログが表示されるタイミングが謎である。
以下の流れにしたら動いた。
-
- ウィンドウA設定反映ボタン押下時のコールバックで
- Dialogを作成、dialog.show_all, dialog.runまでやってしまう
- Dialogの、"show"シグナルハンドラを作る
- showシグナルハンドラの中で、設定反映スレッドを実行
- ウィンドウA設定反映ボタン押下時のコールバックで
こうすると、ダイアログが表示された後で、スレッドが実行されることが保証される。
その3
上が動いた状態で。。
- ウィンドウA設定反映ボタン押下
- ダイアログB開く、スレッドが走る
- スレッドの中で、ウィンドウAのラベルの値を変える
というプログラムもうまく動かず。動くとき、動かない時がある。ウィンドウが真っ白になったり。
これはあきらめる。