質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.99%

pythonで親と子プロセスからの結果を同時にリアルタイム表示&ファイル格納したい

受付中

回答 0

投稿

  • 評価
  • クリップ 0
  • VIEW 534

pac727

score 7

 前提・実現したいこと

python3のsubprocess.Popenを用いてネットワーク性能測定(iperf3)コマンドを実行しつつ、親処理でも別のパケット送受信テストを実行しています。途中結果をリアルタイムで画面表示すると同時にファイルへも格納すべく実装中ですが期待通りにはいっていません。環境はpython 3.7.0, MacOS 10.13.5です。

 発生している問題

一口で言うと①リアルタイム画面表示だけの時は、期待通りの出力結果となりますが、②ファイル格納のみ、および③リアルタイム画面表示とファイル格納・同時、の時は期待とは異なります。③が実現できず困っています。

 該当のソースコード

実装とほぼ等価と思われるpython3スクリプトで問題を説明します。
親は(調査のため)二種類用意し、printの繰り返し実行をforにより一定回数実行後終了するものと、while True:によりctl-C押下時まで継続するものです。 子は起動後二度printし終了します。

#parent_f.py
import subprocess
import time
import datetime
import sys

print("parent 1",datetime.datetime.now().strftime("%T"))
time.sleep(1)
cmd = "Python3 child.py"
subprocess.Popen(cmd,shell=True)
time.sleep(1) 
for i in range(7):
    print("parent 2",datetime.datetime.now().strftime("%T"))
    time.sleep(1)
#parent_w.py
import subprocess
import time
import datetime
import sys

print("parent 1",datetime.datetime.now().strftime("%T"))
time.sleep(1)
cmd = "Python3 child.py"
subprocess.Popen(cmd,shell=True)
time.sleep(1) 
try:
    while True: 
        print("parent 2",datetime.datetime.now().strftime("%T"))
        time.sleep(1)
except KeyboardInterrupt:
    print("## Ctl_C pressed")
    sys.exit(0)    ```  
#child.py  
import time  
import datetime  

print("child 1",datetime.datetime.now().strftime("%T"))  
time.sleep(4)  
print("child 2", datetime.datetime.now().strftime("%T"))  

 試したこと

(1)①画面表示のみの結果
  for繰り返し、while繰り返し共に期待通りの出力です。

$ python3 parent_f.py 2>&1   
parent 1 06:20:31  
child 1 06:20:32  
parent 2 06:20:33  
parent 2 06:20:34  
parent 2 06:20:35  
parent 2 06:20:36  
child 2 06:20:36  
parent 2 06:20:37  
parent 2 06:20:38  
parent 2 06:20:39  
$ python3 parent_w.py 2>&1  
parent 1 06:05:10  
child 1 06:05:11  
parent 2 06:05:12  
parent 2 06:05:13  
parent 2 06:05:14  
parent 2 06:05:15  
child 2 06:05:15  
parent 2 06:05:16  
parent 2 06:05:17  
parent 2 06:05:18  
parent 2 06:05:19  
parent 2 06:05:20  
parent 2 06:05:21  
parent 2 06:05:22  
^C## Ctl_C pressed    

(2)②ファイル格納のみ
  for繰り返し、while繰り返し共に何故か、子と親プロセスの出力がまとめられます。 

$ python3 parent_f.py 2>&1 > test33.txt  
$ cat test33.txt  
child 1 06:34:19  
child 2 06:34:23  
parent 1 06:34:18  
parent 2 06:34:20  
parent 2 06:34:21  
parent 2 06:34:22  
parent 2 06:34:23  
parent 2 06:34:24  
parent 2 06:34:25  
parent 2 06:34:26  
$ python3 parent_w.py 2>&1 > test3.txt  
^C$ cat test3.txt  
child 1 06:14:26  
child 2 06:14:30  
parent 1 06:14:25  
parent 2 06:14:27  
parent 2 06:14:28  
parent 2 06:14:29  
parent 2 06:14:30  
parent 2 06:14:31  
parent 2 06:14:32  
parent 2 06:14:33  
## Ctl_C pressed  

(3)③リアルタイム画面表示とファイル格納・同時

teeを用いました。 for繰り返しでは、リアルタイム表示は子と親プロセスの出力がまとめられ、かつ非リアルタイム表示(それぞれのプロセス終了時に一気に表示される感じ)です。ファイル格納は②と同じで子と親プロセスの出力がまとめられます。

$ python3 parent_f.py 2>&1 |tee  test44.txt  
child 1 09:35:28  
child 2 09:35:32  
parent 1 09:35:27  
parent 2 09:35:29  
parent 2 09:35:30  
parent 2 09:35:31  
parent 2 09:35:32  
parent 2 09:35:33  
parent 2 09:35:34  
parent 2 09:35:35  
$ cat test44.txt  
child 1 09:35:28  
child 2 09:35:32  
parent 1 09:35:27  
parent 2 09:35:29  
parent 2 09:35:30  
parent 2 09:35:31  
parent 2 09:35:32  
parent 2 09:35:33  
parent 2 09:35:34  
parent 2 09:35:35  

while繰り返しではリアルタイム表示は子プロセスのみとなり、かつ非リアルタイム表示(子プロセス終了時に一気に表示される感じ)です。ファイル格納も子プロセスの出力のみ格納されます。

$ python3 parent_w.py 2>&1 |tee  test4.txt  
child 1 09:39:45  
child 2 09:39:49  
^C  
$ cat test4.txt  
child 1 09:39:45  
child 2 09:39:49  

以上が試行結果です。 本件はネットワーク性能の連続実測に用いたいため、while繰り返し型で③リアルタイム画面表示とファイル格納・同時を実現したいと考えています。親子プロセス同居環境でteeを用いると、非リアルタイム表示になる、ctlーC中断された親プロセスの出力はファイル格納されない、との問題が残っております。解法をご教示願います。
なお、解法の優先順位としては、リアルタイム表示>ファイル格納(ファイル格納では親、子それぞれのプロセスで出力にタイムスタンプを付与するので、子と親プロセスの出力が上記(2)のようにまとめられても何とかなる)を希望しています。また、tee使用は固執しません。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正の依頼

  • t_obara

    2018/08/31 11:29

    print("", flush=True) のようにflushオプションを有効にすると変わりますか?

    キャンセル

  • pac727

    2018/08/31 12:15

    早速の回答を頂きありがとうございます。とりあえずwhile繰り返し型で試行しました。親、子の全printにflush=Trueを追加したところ、|teeによりほとんど期待通りの結果(リアルタイム表示、ファイル格納)が得られました。 (1)Ctlーc押下時、|tee無しの表示オンリーでは期待通り## Ctl_C pressedも表示され停止します。しかし|tee有りの時は## Ctl_C pressedについては表示もファイル格納もありません。運用上大きな妨げではありませんが。 (2)flush=True指定する場合のデメリット、留意点などございましたらご教示ください。(3)蛇足ですが、本番で使用する子プロセス(iperf3コマンド)には--forceflushオプションがありましたので|teeで試行したところ期待通りの結果(リアルタイム表示、ファイル格納)が得られました。

    キャンセル

  • otn

    2018/08/31 14:33

    一般的にプログラムは、出力先が端末の時はバッファリング無しで、端末以外の時はバッファリングしますので、こういう目的の時はバッファリングしないようなオプションが必要です。

    キャンセル

  • otn

    2018/08/31 14:40

    teeを使ったときは、ctrl-Cはteeに送られ、python3に送られる事はありません。

    キャンセル

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる