🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Python 3.x

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

Q&A

解決済

1回答

1943閲覧

Pythonのsubprocessでのコマンドの実行

Kitano

総合スコア15

Python 3.x

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

0グッド

0クリップ

投稿2020/12/24 06:13

前提・実現したいこと

Pythonのsubprocessモジュールを用いてコマンドを実行したいのですが要求通りに動かす事ができません。具体的には以下の通りです。

発生している問題

プログラムAを動作させる際にはソフトウェアBが立ち上がっている必要がある。
またプログラムAの起動にはソフトウェアBが起動時に出力する情報が必要である。
その為、これらをプログラムCを用いてまとめて起動できる様にしようとしたがプログラムCで問題が発生した。
subprocess.PopenでソフトウェアBを実行したがsubprocess.Popenは実行結果がコマンド終了後にしか取得できない為、ソフトウェアB起動時の情報を取得できず、また終了すれば情報を取得出来るが、今度はプログラムAを実行できない為、意味が無く、今回は使えなかった。
また実行時に逐次結果を出力出来るsubprocess.check_outputも試したがこちらは同期処理でコマンド終了まで次の処理が実行できない為、プログラムAを実行出来ず、今回は使えなかった。

この様な使い方はsubprocessモジュールでは無理なのでしょうか?
その場合、無駄な感じがしてあまり使いたく無いのですがprocessモジュールを使ってプロセスを分けるしかないのでしょうか?

該当のソースコード

Python3.7

1import subprocess 2from subprocess import PIPE 3import time 4import sys 5 6import mains 7 8socat = subprocess.Popen("hogehoge", shell=True, stdout=PIPE, stderr=PIPE, text=True) 9# socat = subprocess.check_output("hogehoge", shell=True) 10time.sleep(1) 11msg = socat.stdout.readreadline() 12print(msg) 13split_data = msg.split() 14socat_port = split_data[6] 15 16mains.main(socat_port) 17 18socat.kill()

試したこと

発生している問題に書いた通りです。

補足情報(FW/ツールのバージョンなど)

実行環境
RaspberryPi3
Python3.7.3

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

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

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

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

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

guest

回答1

0

ベストアンサー

subprocess.Popenは実行結果がコマンド終了後にしか取得できない

そんなことは無いので、プログラムB内でバッファリングされて、パイプに出力されていないんだと思います。
プログラムBが修正可能なら、必要情報を出力した後でflushすれば良いと思います。

投稿2020/12/24 06:56

otn

総合スコア85886

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

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

Kitano

2020/12/24 07:41

そうなんですか? ソフトウェアBをbashでそのまま実行すると ソフトウェアBは自分で作成したプログラムではなくLinuxのコマンドなので修正は厳しいです。
otn

2020/12/24 07:44

bashコマンドラインで、 soft-b | cat で、パイプ経由でcatにつないで、メッセージが見えますか?
Kitano

2020/12/24 07:47

soft-b | catの番号は見えます また先ほど誤って途中で送信してしまったので再送します。 そうなんですか? ソフトウェアBをbashでそのまま実行すると結果が画面に表示されるのですがsubprocessで実行すると出力されてこないんです。 ソフトウェアBは自分で作成したプログラムではなくLinuxのコマンドなので修正は避けたいです。
Kitano

2020/12/24 07:48

すみません 番号ではなく場合です。
otn

2020/12/24 07:49

soft-b 2>&1 | cat か。
Kitano

2020/12/24 08:01

soft-b 2>&1 | cat の場合も出てきました。 今回subprocess.Popenが実行した処理が終わらないと実行の結果が取得出来ないと判断した理由が作成したプログラムが毎回途中で止まり、そのたびにctr-cで停止させると決まってTraceback (most recent call last)の欄がmsg=socat.stdout.readreadline()の行なのでBが終了しないと結果が取れず、結果が読み取れないので止まっているのではと判断したのですがそもそもこの時点で勘違いをしていたのでしょうか?
otn

2020/12/24 08:14

subprocess.Popen の機能としてはそういうことは無いです。 念のため、 subprocess.Popen("stdbuf -o0 -e0 hogehoge", shell=True, stdout=PIPE, stderr=PIPE, text=True) でどうでしょうか? stdbufコマンドがない場合はインストールしてください。
Kitano

2020/12/24 09:00

subprocess.Popen("stdbuf -o0 -e0 hogehoge", shell=True, stdout=PIPE, stderr=PIPE, text=True)とした場合も止まり、ctr-cで停止させるとやはりTraceback (most recent call last)の欄がmsg=socat.stdout.readreadline()の行になっていました。 念の為、別の環境でも動かしてみましたが同じ結果でした。 またstdbuf -o0 -e0 hogehogeの部分単体をshellで実行したところきちんと表示されました。 このままでは埒があきそうもなく、仕方がないのでhogehogeとしていた箇所のコマンドを出します。 hogehogeとしていた箇所のコマンドはsocat -d -d pty,raw,echo=0 pty,raw,echo=0で、クロスのシリアルポートを作成していました。
otn

2020/12/24 10:47

bashコマンドラインで、 socat -d -d pty,raw,echo=0 pty,raw,echo=0 2>&1 | cat でちゃんと動くのでしょうか?
Kitano

2020/12/25 09:17

最初の方に指摘され、試した際に動かした際に出力は出ています。 またもう一度実行してみましたが同じように動き、出力されました。
otn

2020/12/25 12:46

失礼。 2>&1 の場合も聞いてましたね。 このプログラム自体は、どうやって実行していますか? シェルのプロンプトで、python ファイル名 ですか?
Kitano

2020/12/25 13:13

はい その通りです。 「python3 ファイル名」で実行しています。
otn

2020/12/25 14:09

すいません、ちゃんと見られてませんでした。 subprocess.Popen("hogehoge", shell=True, stdout=PIPE, stderr=STDOUT, text=True) で。 あるいは、そこはそのままで、 msg = socat.stderr.readline() でもいいです。
Kitano

2020/12/26 15:10

返信が遅くなりすみません。 msg = socat.stderr.readline()にて解決しました。 socatの生成したポート番号の情報が標準エラー出力に出ていたとは盲点でした。接続時に必要なデータなのでてっきり標準出力に出ている物と思っていました。思い込みは良くないと反省しているしだいです。 今回は長時間に渡って対応していただき本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問