#navi_header|Python| かなりニッチなモデルについて実験。 + スレッド1:対話形式処理モードと監視処理モードの二つのモードの間を遷移する。 + スレッド2:コンソールでCtrl-Cによる割り込みを受け付け、スレッド1を対話形式処理モードに切り替える。 スレッド1の監視処理はbusyループではなく、TimeOut付きの短期間のwait()を無限ループ中で呼び出すイメージ。 スレッド1の初期状態は監視処理モード。スレッド2による切り替えで対話形式処理モードに遷移する。 対話形式処理モードにおいて監視処理への切り替えコマンドを受け取ると、再び監視処理モードに遷移する。 スレッド間の連携については threading.Event を使ってみる。 予備実験として threading.Event を使ったスレッド間連携を試してみる。 thread_and_event1.py: #code|python|> import threading import time def mythread(myevent): count = 1 while True: myevent.wait(1) print "wakeup(%d)" % (count) count += 1 if myevent.isSet(): print "break" break event = threading.Event() t = threading.Thread(target=mythread, args=(event,)) t.start() # 5秒後にevent発生 time.sleep(5) print "(main):event set" event.set() t.join() ||< 実行例(Python2.5) #pre||> > python thread_and_event1.py wakeup(1) wakeup(2) wakeup(3) wakeup(4) (main):event set wakeup(5) break > ||< 予備実験で threading.Event によるスレッド間連携を確認できた。 本題となるモード切り替えやCtrl-Cによるスレッド連携の実装サンプル: thread_and_event2.py: #code|python|> import threading import time import signal def mythread(myevent): busy_work = threading.Event() # 小刻みな監視処理用のダミーEvent continue_flag = True count = 1 while continue_flag: # 小刻みな監視処理 if busy_work.wait(1): print "Never happen" else: print "mythread(%d)" % (count) count += 1 # 連携イベントをチェック myevent.wait(1) if myevent.isSet(): print "Interrupted" # 対話形式スタート while True: command = raw_input(">>") if command == "q": continue_flag = False break # 監視処理に戻る+フラグにより終了へ elif command == "g": break # 監視処理に戻る else: print "You type: " + command myevent.clear() print "end" event = threading.Event() t = threading.Thread(target=mythread, args=(event,)) t.start() while True: try: # 1秒間ずつスレッドの終了チェック t.join(1) if not t.isAlive(): break except KeyboardInterrupt: # Ctrl-C による割り込み発生 print "interruption set" event.set() ||< 実行例(Python2.5) #pre||> > python thread_and_event2.py mythread(1) mythread(2) mythread(3) (Ctrl-C) interruption set Interrupted >>foo You type: foo >>bar You type: bar >>g mythread(4) mythread(5) (Ctrl-C) interruption set mythread(6) Interrupted >>abc You type: abc >>q end > ||< Ctrl-Cによる監視→対話へ切り替え、対話形式でのコマンド入力による監視モードへの復帰やスレッドの終了を実現できた。 なお raw_input() 中に Ctrl-C を受信するとEOFErrorが発生する点に注意が必要。 EOF発生時には空文字列入力として続行する例: # 対話形式スタート while True: command = raw_input(">>") → # 対話形式スタート while True: command = "" try: command = raw_input(">") except EOFError: pass #navi_footer|Python|