サブプロセス実行メソッドを使用してPythonでシェルコマンドを実行する方法

How Execute Shell Commands Python Using Subprocess Run Method



サブプロセスは、新しいプロセスを作成し、それらの入力および出力データストリームと対話するために使用できる組み込みのPythonモジュールです。簡単に言うと、シェルコマンドを実行したり、Linuxファイルシステム全体のさまざまなbinフォルダーに通常散在している実行可能バイナリを実行したりするために使用できます。実行可能バイナリへのフルパスを指定して、バイナリに関連付けられているコマンドラインスイッチを使用することもできます。この記事では、Pythonアプリでサブプロセスモジュールとその実行メソッドを使用する方法について説明します。この記事のすべてのコードサンプルは、Ubuntu20.04のPython3.8.2でテストされています。

Subprocess.runメソッド

Subprocess.runメソッドは、引数のリストを取ります。メソッドが呼び出されると、コマンドが実行され、プロセスが終了するのを待ち、最後にCompletedProcessオブジェクトを返します。 CompletedProcessオブジェクトは、stdout、stderr、メソッドの呼び出し中に使用された元の引数、および戻りコードを返します。 Stdoutはコマンドによって生成されたデータストリームを指し、stderrはプログラムの実行中に発生したエラーを指します。ゼロ以外の戻りコード(終了コード)は、subprocess.runメソッドで実行されたコマンドのエラーを意味します。







例1:Subprocess.runメソッドを使用してテキストファイルの内容を出力する

以下のコマンドは、name = John文字列が含まれていると仮定して、data.txtファイルの内容を出力します。



輸入 サブプロセス
サブプロセス走る((['猫' 'data.txt'])。

上記のコードを実行すると、次の出力が返されます。



名前=ジョン
CompletedProcess((args=['猫' 'data.txt']リターンコード=0)。

list引数の最初の要素は、実行するコマンドの名前です。最初の要素に続くリスト内の要素はすべて、コマンドラインオプションまたはスイッチと見なされます。オプションを定義するために、一重ダッシュと二重ダッシュを使用することもできます。たとえば、ディレクトリ内のファイルとフォルダを一覧表示するには、コードはsubprocess.run([ls、-l]になります。これらのほとんどの場合、シェルコマンドのスペースで区切られた引数は、の個々の要素と見なすことができます。 subprocess.runメソッドに提供されるリスト。





例2:Subprocess.runメソッドの出力を抑制する

subprocess.runメソッドの出力を抑制するには、追加の引数としてstdout = subprocess.DEVNULLおよびstderr = subprocess.DEVNULLを指定する必要があります。

輸入 サブプロセス

サブプロセス走る((['猫' 'data.txt']stdout=サブプロセスDEVNULL
stderr=サブプロセスDEVNULL)。

上記のコードを実行すると、次の出力が生成されます。



CompletedProcess(args = ['cat'、 'data.txt']、returncode = 0)

例3:Subprocess.runメソッドの出力をキャプチャする

subprocess.runメソッドの出力をキャプチャするには、capture_output = Trueという名前の追加の引数を使用します。

輸入 サブプロセス
出力= サブプロセス走る((['猫' 'data.txt']Capture_output=NS)。
印刷 ((出力)。

上記のコードを実行すると、次の出力が生成されます。

CompletedProcess((args=['猫' 'data.txt']リターンコード=0
stdout=NS'名前=ジョンNS'stderr=NS'')。

output.stdoutメソッドとoutput.stderrメソッドを使用して、stdout値とstderr値に個別にアクセスできます。出力はバイトシーケンスとして生成されます。文字列を出力として取得するには、output.stdout.decode(utf-8)メソッドを使用します。 subprocess.run呼び出しに追加の引数としてtext = Trueを指定して、文字列形式で出力を取得することもできます。終了ステータスコードを取得するには、output.returncodeメソッドを使用できます。

例4:Subprocess.runメソッドによって実行されたコマンドの失敗時に例外を発生させる

コマンドがゼロ以外のステータスで終了したときに例外を発生させるには、check = True引数を使用します。

輸入 サブプロセス
サブプロセス走る((['猫' 'data.tx']Capture_output=NS文章=NSチェック=NS)。

上記のコードを実行すると、次の出力が生成されます。

CalledProcessError(retcode、process.args、
subprocess.CalledProcessError:コマンド '[' cat '、' data.tx ']'
ゼロ以外の終了ステータス1が返されました。

例5:Subprocess.runメソッドによって実行されるコマンドに文字列を渡す

input = ’string’引数を使用して、subprocess.runメソッドによって実行されるコマンドに文字列を渡すことができます。

輸入 サブプロセス
出力= サブプロセス走る((['猫'] 入力='data.txt'Capture_output=NS
文章=NSチェック=NS)。
印刷 ((出力)。

上記のコードを実行すると、次の出力が生成されます。

CompletedProcess(args = ['cat']、returncode = 0、stdout = 'data.txt'、stderr = '')

ご覧のとおり、上記のコードはdata.txtをファイルオブジェクトとしてではなく文字列として渡します。 data.txtをファイルとして渡すには、stdin引数を使用します。

開いた(('data.txt')。 なのでNS:
出力= サブプロセス走る((['猫']stdin=NSCapture_output=NS
文章=NSチェック=NS)。
印刷 ((出力)。

上記のコードを実行すると、次の出力が生成されます。

CompletedProcess(args = ['cat']、returncode = 0、stdout = 'name = John n'、stderr = '')

例6:Subprocess.runメソッドを使用してシェルでコマンドを直接実行する

メインコマンドとそれに続くオプションで文字列分割を使用する代わりに、コマンドをそのままシェルに直接実行することができます。これを行うには、追加の引数としてshell = Trueを渡す必要があります。ただし、shell = Trueを使用するとセキュリティの問題が発生する可能性があるため、Python開発者はこれを推奨していません。セキュリティへの影響について詳しくは、 ここ

輸入 サブプロセス
サブプロセス走る(('cat' data.txt ''シェル=NS)。

上記のコードを実行すると、次の出力が生成されます。

名前=ジョン

結論

Pythonのsubprocess.runメソッドは、Python自体の中でシェルコマンドを実行できるため、非常に強力です。これは、個別のファイルに追加のシェルスクリプトコードを含める必要なしに、すべてのコードをPython自体に制限するのに役立ちます。ただし、Pythonリストでシェルコマンドを正しくトークン化するのは非常に難しい場合があります。 shlex.split()メソッドを使用して、単純なシェルコマンドをトークン化できますが、長くて複雑なコマンド、特にパイプシンボルを含むコマンドでは、shlexはコマンドを正しく分割できません。このような場合、デバッグは難しい問題になる可能性があります。 shell = True引数を使用してこれを回避できますが、このアクションに関連する特定のセキュリティ上の懸念があります。