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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

0回答

1645閲覧

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

pac727

総合スコア9

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2018/08/31 01:24

前提・実現したいこと

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

発生している問題

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

該当のソースコード

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

Python3

1#parent_f.py 2import subprocess 3import time 4import datetime 5import sys 6 7print("parent 1",datetime.datetime.now().strftime("%T")) 8time.sleep(1) 9cmd = "Python3 child.py" 10subprocess.Popen(cmd,shell=True) 11time.sleep(1) 12for i in range(7): 13 print("parent 2",datetime.datetime.now().strftime("%T")) 14 time.sleep(1)

Python3

1#parent_w.py 2import subprocess 3import time 4import datetime 5import sys 6 7print("parent 1",datetime.datetime.now().strftime("%T")) 8time.sleep(1) 9cmd = "Python3 child.py" 10subprocess.Popen(cmd,shell=True) 11time.sleep(1) 12try: 13 while True: 14 print("parent 2",datetime.datetime.now().strftime("%T")) 15 time.sleep(1) 16except KeyboardInterrupt: 17 print("## Ctl_C pressed") 18 sys.exit(0) ```

python3

1#child.py 2import time 3import datetime 4 5print("child 1",datetime.datetime.now().strftime("%T")) 6time.sleep(4) 7print("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使用は固執しません。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

t_obara

2018/08/31 02:29

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

2018/08/31 03: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 05:33

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

2018/08/31 05:40

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問