ちょっといきぬき

vimとかpythonとかロボットとかMLとか環境構築とかの興味ある技術のことを書きたいだけの人生だった。

【解決?】subprocessを非同期実行しつつ、確実にkillしたい

具体的にはarecordで音声ストリームを取得しつつ、任意のイベントを受け取るかデストラクタで確実にkillしたい。

以下のような一連のコードをThreadで実行している。

self.buff = Queue.Queue(1000)
reccmd = ["arecord", "-f", "S16_LE", "-r", "16000", "-t", "raw", "-q"]

process = subprocess.Popen(reccmd, stdout=subprocess.PIPE)

logger.debug("start buffering process")

self.flag_Buffering = True
while self.flag_Buffering:
    self.buff.put(process.stdout.read(2048))

logger.debug("killing buffering process")
process.kill()

時たまkillできずに子プロセスが居残っているのか、再度実行した時にクラッシュする。
無限ループをフラグで管理している部分が怪しい。

デストラクタでのフラグ変更は確実に呼び出される保証が無いが、 with文なら上手くいく…?

withクラスの実装。

2018年1月30日追記

発話区間の音声を取得するためにbuffというQueueを作り、 発話の検知イベントの遅れを加味して発話前のコンマ数秒からbuffに残し、 発話終わりのイベントが来たタイミングで録音終了、subprocessをkillしたかった。

そもそも別スレッドで実行する必要が無かったので メインスレッドのイベントループ内でstdout.read()した。

素直に動いてくれたけどタイトルの非同期実行しつつ確実にkillは相変わらず不明。 withか。

その他備忘録メモ

process.stdout.read()を使う時にパイプバッファが詰まって デッドロックするのでcommunicate()を使おうという記事を多々見たが ストリームの取得はstdout.read()しか方法が無い様子