パイプで「サブプロセス」コマンドを使用する方法


246

で使用subprocess.check_output()したいps -A | grep 'process_name'。私はさまざまな解決策を試しましたが、これまでのところ何もうまくいきませんでした。誰かがそれを行う方法を私に案内できますか?



4
そこにあるpsutilことは、移植可能な方法でプロセス情報を取得することができます。
jfs 2013年

回答:


438

subprocessモジュールでパイプを使用するには、を渡す必要がありますshell=True

ただし、これはさまざまな理由で実際にはお勧めできません。特にセキュリティがその理由です。代わりに、psgrepプロセスを別々に作成し、次のように出力を一方から他方にパイプします。

ps = subprocess.Popen(('ps', '-A'), stdout=subprocess.PIPE)
output = subprocess.check_output(('grep', 'process_name'), stdin=ps.stdout)
ps.wait()

あなたの特定のケースでは、しかし、簡単な解決策は呼び出すことですsubprocess.check_output(('ps', '-A'))当時とstr.find出力に。


81
+1使用を避けるために出力/入力を分離するshell=True
Nicolas

5
忘れないでください。エラーはsubprocess.CalledProcessError: Command '('grep', 'process_name')' returned non-zero exit status 1単にgrepで何も見つからなかったことを意味するので、これは正常な動作です。
セルジュ

2
ps.wait()すでに出力があるのに、なぜfor が必要なのですか。ps.wait.__doc__は子が終了するのを待ちますが、子の内容はすでにoutput変数に入れられているようです
Papouche Guinslyzinho '25

3
あなたが見ている@MakisH string.findの賛成で廃止されました、str.find(すなわち、法find上のstrオブジェクト)。
Taymon

4
注:grep早期に死亡した場合。psOSパイプバッファーを満たすのに十分な出力が生成されると、無期限にハングする可能性があります(ps.stdout.close()親で呼び出していないため)。それを避けるために、開始順序を入れ替えてください
jfs

54

または、常にサブプロセスオブジェクトで通信メソッドを使用できます。

cmd = "ps -A|grep 'process_name'"
ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
output = ps.communicate()[0]
print(output)

通信メソッドは、標準出力と標準エラーのタプルを返します。


3
を使用するcommunicate方が良いと思いますwaitそのような警告があります:「これはstdout = PIPEおよび/またはstderr = PIPEを使用するとデッドロックし、子プロセスが十分な出力をパイプに生成するため、OSパイプバッファーがさらに多くのデータを受け入れるのをブロックします。communication()を使用してそれを避けなさい。」
Paolo

2
上記のパオロのコメントを明確にするために、警告はコミュニケーションのためではなく待機のためです-つまり、コミュニケーションが優れていると彼が言う理由です。
EnemyBagJones

23

サブプロセスを使用したパイプラインの設定に関するドキュメントを参照してください:http : //docs.python.org/2/library/subprocess.html#replacing-shell-pipeline

私は次のコード例をテストしていませんが、大体あなたが望むものであるはずです:

query = "process_name"
ps_process = Popen(["ps", "-A"], stdout=PIPE)
grep_process = Popen(["grep", query], stdin=ps_process.stdout, stdout=PIPE)
ps_process.stdout.close()  # Allow ps_process to receive a SIGPIPE if grep_process exits.
output = grep_process.communicate()[0]

2
これが失敗したチェックの際に、周りいじくるなしで動作し、何かのためにTaymonにより下記の回答を参照してください
アルビン

2
subprocess.check_outputはPython 2.6.9に存在しないようです
RightmireM

6

JKALAVISソリューションは優れていますが、SHELL = TRUEの代わりにshlexを使用するように改善を加えます。以下クエリ時間をgreppingアウト

#!/bin/python
import subprocess
import shlex

cmd = "dig @8.8.4.4 +notcp www.google.com|grep 'Query'"
ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
output = ps.communicate()[0]
print(output)

1
なぜshellxよりshellxなのですか?
AFP_555 2018年

2
ここでshlexはどこで使用されますか?
3lokh

4

また、'pgrep'代わりにコマンドを使用してみてください'ps -A | grep 'process_name'


2
プロセスIDを取得したい場合、明らかに
Shooe


0

Python 3.5以降では、次も使用できます。

    import subprocess

    f = open('test.txt', 'w')
    process = subprocess.run(['ls', '-la'], stdout=subprocess.PIPE, universal_newlines=True)
    f.write(process.stdout)
    f.close()

コマンドの実行はブロックされ、出力はprocess.stdoutにあります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.