Python subprocess モジュール
subprocessは Python 標準ライブラリのモジュールであり、サブプロセスの作成と管理に使用されます。
subprocessPython プログラム内で外部コマンドを実行し、それらのコマンドと対話することを可能にします。
このsubprocessモジュールを使用すると、システムコマンドを実行したり、他のプログラムを呼び出したり、それらの出力やエラー情報を取得したりできます。
なぜ subprocess モジュールを使うのか?
Python では、特定のタスクを完了するためにシステムコマンドを実行したり、他のプログラムを呼び出したりする必要がある場合があります。例えば、シェルコマンドの実行、外部アプリケーションの起動、またはコマンドラインツールとの対話が必要になるかもしれません。subprocessモジュールは、これらのニーズに対応するための安全で柔軟な方法を提供します。
初期のos.system() 或 os.popen()と比較して、subprocessモジュールはより強力な機能と優れた制御能力を提供します。サブプロセスの入力、出力、エラーストリームをより細かく管理でき、より複雑なシナリオも処理できます。
subprocess モジュールの核心機能
1. 外部コマンドを実行する
subprocess.run()であるsubprocessモジュールで最もよく使われる関数の1つです。外部コマンドを実行し、コマンドの完了を待ちます。以下は簡単な例です:
実例
# 簡単なシェルコマンドを実行する
result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
# コマンドの出力を表示する
print(result.stdout)
この例では、subprocess.run()実行されたのはls -lコマンドで、その出力はresult.stdoutにキャプチャされました。
2. 入力と出力を処理する
subprocessモジュールを使用すると、サブプロセスの入力、出力、エラーストリームを制御できます。データをサブプロセスの標準入力に渡したり、サブプロセスの標準出力や標準エラーからデータを読み取ったりできます。以下は例です:
実例
# コマンドを実行し、入力をサブプロセスに渡す
result = subprocess.run(['grep', 'python'], input='hello\npython\nworld', capture_output=True, text=True)
# コマンドの出力を表示する
print(result.stdout)
この例では、subprocess.run()実行されたのはgrep pythonコマンドで、文字列'hello\npython\nworld'を入力としてサブプロセスに渡しました。
3. エラーを処理する
subprocessモジュールはサブプロセスのエラー処理も可能にします。サブプロセスがゼロ以外の終了ステータスコードを返した場合、subprocess.run()スローされるのはCalledProcessError例外です。[returncode] を確認することで、result.returncodeサブプロセスの終了ステータスコードを取得できます。
実例
try:
result = subprocess.run(['ls', 'nonexistent_file'], capture_output=True, text=True, check=True)
except subprocess.CalledProcessError as e:
print(f"Command failed with return code {e.returncode}")
print(f"Error output: {e.stderr}")
この例では、subprocess.run()実行されたのはls nonexistent_fileコマンドで、ファイルが存在しないため失敗し、スローされたのはCalledProcessError例外です。
subprocess モジュールの上級用法
1. Popen クラスを使用する
subprocess.Popenクラスはより低レベルのインターフェースを提供し、サブプロセスをより柔軟に制御できます。また、[Popen()] を使用してPopen子プロセスを起動し、バックグラウンドで実行したり、対話したりできます。
実例
# 子プロセスを起動する
process = subprocess.Popen(['ping', 'google.com'], stdout=subprocess.PIPE, text=True)
# 子プロセスの出力を読み取る
while True:
output = process.stdout.readline()
if output == '' and process.poll() is not None:
break
if output:
print(output.strip())
# 子プロセスの終了ステータスコードを取得する
return_code = process.poll()
print(f"Process finished with return code {return_code}")
この例では、subprocess.Popen起動されたのはping google.comコマンドで、バックグラウンドで実行されました。プログラムはループを使用して子プロセスの出力を読み取り、子プロセスが終了した後にその終了ステータスコードを取得します。
2. パイプを使用する
subprocessモジュールを使用すると、パイプを使って複数のコマンドを接続できます。あるコマンドの出力を別のコマンドの入力として渡せます。
実例
# パイプを使用して2つのコマンドを接続する
p1 = subprocess.Popen(['ls', '-l'], stdout=subprocess.PIPE)
p2 = subprocess.Popen(['grep', 'py'], stdin=p1.stdout, stdout=subprocess.PIPE, text=True)
# 最終出力を取得する
output = p2.communicate()[0]
print(output)
この例では、ls -lコマンドの出力はgrep pyコマンドに渡され、最終出力にはpyのファイルまたはディレクトリが含まれます。
subprocess モジュールの一般的なメソッド、クラス、パラメータ
以下は、Python subprocessモジュールの一般的なメソッド、クラス、パラメータの説明で、機能の説明と例を含みます:
subprocess モジュールの核心メソッド
| メソッド | 説明 | 例 |
|---|---|---|
subprocess.run() | コマンドを実行して完了を待つ(推奨) | subprocess.run(["ls", "-l"], capture_output=True, text=True) |
subprocess.Popen() | サブプロセスを作成する(低レベル制御) | proc = subprocess.Popen(["ping", "google.com"], stdout=subprocess.PIPE) |
subprocess.call() | コマンドを実行して終了コードを返す(旧版) | exit_code = subprocess.call(["python", "--version"]) |
subprocess.check_call() | コマンドを実行し、失敗時に例外をスローする | subprocess.check_call(["git", "commit"]) |
subprocess.check_output() | コマンドを実行して出力を返す(旧版) | output = subprocess.check_output(["date"], text=True) |
subprocess.CompletedProcess オブジェクトの属性(run() メソッドの戻りオブジェクト)
| 属性 | 説明 |
|---|---|
args | 実行されたコマンドの引数リスト |
returncode | プロセスの終了ステータスコード(0は成功を意味します) |
stdout | 標準出力の内容(設定されている場合capture_output) |
stderr | 標準エラーの内容(設定されている場合capture_output) |
subprocess.Popen クラスの一般的なメソッド/属性
| メソッド/属性 | 説明 | 例 |
|---|---|---|
poll() | プロセスが終了したかどうかを確認(戻り値がNoneの場合は実行中) | if proc.poll() is None: print("Running") |
wait() | ブロックしてプロセスの終了を待つ | proc.wait() |
communicate() | 対話式の入力/出力 | stdout, stderr = proc.communicate(input="data") |
terminate() | 終了シグナル(SIGTERM)を送信する | proc.terminate() |
kill() | プロセスを強制終了する(SIGKILL) | proc.kill() |
stdin | プロセスの標準入力ストリーム | proc.stdin.write("input") |
stdout | プロセスの標準出力ストリーム | print(proc.stdout.read()) |
stderr | プロセスの標準エラーストリーム | errors = proc.stderr.read() |
一般的なパラメータの説明(run() と Popen() に適用)
| パラメータ | 説明 | 例の値 |
|---|---|---|
args | コマンド(リストまたは文字列) | ["ls", "-l"] 或 "ls -l" |
stdin | 標準入力の設定 | subprocess.PIPE(パイプ)、None(継承) |
stdout | 標準出力の設定 | subprocess.PIPE、open('log.txt', 'w') |
stderr | 標準エラーの設定 | subprocess.STDOUT(stdoutに統合) |
shell | Shellを介して実行するかどうか | True(文字列コマンドをサポート) |
cwd | 作業ディレクトリのパス | "/tmp" |
env | カスタム環境変数 | {"PATH": "/usr/bin"} |
timeout | タイムアウト時間(秒) | 30 |
text | 入出力が文字列かどうか(バイトではない) | True |
実例
コマンドを実行して出力をキャプチャする:
実例
print(result.stdout) # 出力: "Hello\n"
Shellを介して複雑なコマンドを実行する:
subprocess.run("grep 'error' log.txt | wc -l", shell=True, check=True)出力ストリームをリアルタイムで取得する:実例
while True:
line = proc.stdout.readline()
if not line: break
print(line.decode().strip())
タイムアウト制御:
実例
subprocess.run(["sleep", "10"], timeout=5)
except subprocess.TimeoutExpired:
print("コマンドがタイムアウトしました!")