[Python] subprocess.run関数の使い方 – サブプロセスの起動
subprocess.run関数は、Pythonで外部コマンドやプログラムを実行するために使用されます。
この関数は、サブプロセスを起動し、その終了を待機します。
基本的な使い方はsubprocess.run(["コマンド", "引数1", "引数2"], options)
の形式で、リスト形式でコマンドと引数を指定します。
オプションとして、capture_output=True
で標準出力とエラーを取得したり、text=True
で出力を文字列として扱ったりできます。
戻り値はCompletedProcess
オブジェクトで、returncode
やstdout
などにアクセス可能です。
subprocess.run関数とは
subprocess.run
関数は、Pythonのsubprocess
モジュールに含まれる関数で、外部プログラムやコマンドを実行するために使用されます。
この関数を利用することで、Pythonスクリプトからシェルコマンドを呼び出したり、他のプログラムを実行したりすることができます。
主な特徴
- 簡単なインターフェース:
subprocess.run
は、外部コマンドを実行するためのシンプルな方法を提供します。 - 結果の取得: 実行したコマンドの標準出力や標準エラー出力を簡単に取得できます。
- エラーハンドリング: コマンドの実行結果に基づいてエラー処理を行うことができます。
以下は、subprocess.run
を使用してls
コマンドを実行する例です。
import subprocess
# lsコマンドを実行
result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
# 実行結果を表示
print(result.stdout)
このコードを実行すると、カレントディレクトリのファイルリストが表示されます。
出力結果は以下のようになります。
total 0
-rw-r--r-- 1 user group 0 date time filename
subprocess.run
は、シンプルでありながら強力な機能を持っているため、さまざまな場面で活用されます。
基本的な使い方
subprocess.run
関数の基本的な使い方を理解するために、まずはその構文を見てみましょう。
基本的な構文は以下の通りです。
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, check=False)
引数の説明
引数名 | 説明 |
---|---|
args | 実行するコマンドとその引数をリスト形式で指定します。 |
stdin | 標準入力を指定します。 |
stdout | 標準出力を指定します。 |
stderr | 標準エラー出力を指定します。 |
shell | True に設定すると、シェルを介してコマンドを実行します。 |
check | True に設定すると、コマンドが失敗した場合に例外を発生させます。 |
シンプルな例
以下は、echo
コマンドを使用して文字列を表示するシンプルな例です。
import subprocess
# echoコマンドを実行
result = subprocess.run(['echo', 'Hello, World!'], capture_output=True, text=True)
# 実行結果を表示
print(result.stdout)
Hello, World!
注意点
args
には、コマンド名とその引数をリスト形式で指定する必要があります。capture_output=True
を指定することで、標準出力と標準エラー出力をキャプチャできます。text=True
を指定すると、出力がバイナリではなく文字列として取得できます。
このように、subprocess.run
を使うことで、外部コマンドを簡単に実行し、その結果を取得することができます。
オプションの活用方法
subprocess.run
関数には、コマンドの実行を制御するためのさまざまなオプションがあります。
これらのオプションを活用することで、より柔軟に外部コマンドを実行することができます。
以下に、主なオプションの使い方を紹介します。
checkオプション
check
オプションをTrue
に設定すると、コマンドが失敗した場合にCalledProcessError
例外が発生します。
これにより、エラーハンドリングが容易になります。
import subprocess
try:
# 存在しないコマンドを実行
result = subprocess.run(['nonexistent_command'], check=True)
except subprocess.CalledProcessError as e:
print(f"エラーが発生しました: {e}")
cwdオプション
cwd
オプションを使用すると、コマンドを実行する作業ディレクトリを指定できます。
import subprocess
# 特定のディレクトリでlsコマンドを実行
result = subprocess.run(['ls'], cwd='/path/to/directory', capture_output=True, text=True)
# 実行結果を表示
print(result.stdout)
shellオプション
shell
オプションをTrue
に設定すると、シェルを介してコマンドを実行できます。
これにより、パイプやリダイレクトなどのシェル機能を利用できます。
import subprocess
# シェルを介してコマンドを実行
result = subprocess.run('echo Hello, World! | tr " " "-"', shell=True, capture_output=True, text=True)
# 実行結果を表示
print(result.stdout)
inputオプション
input
オプションを使用すると、コマンドに標準入力を渡すことができます。
import subprocess
# echoコマンドに標準入力を渡す
result = subprocess.run(['cat'], input='Hello, World!', capture_output=True, text=True)
# 実行結果を表示
print(result.stdout)
timeoutオプション
timeout
オプションを指定すると、コマンドの実行時間に制限を設けることができます。
指定した時間内にコマンドが終了しない場合、TimeoutExpired
例外が発生します。
import subprocess
try:
# 長時間実行されるコマンドを実行(例としてsleepを使用)
result = subprocess.run(['sleep', '10'], timeout=5)
except subprocess.TimeoutExpired:
print("コマンドがタイムアウトしました。")
これらのオプションを活用することで、subprocess.run
関数をより効果的に利用できるようになります。
状況に応じて適切なオプションを選択し、外部コマンドの実行を制御しましょう。
標準入出力の操作
subprocess.run
関数を使用すると、外部コマンドの標準入出力を簡単に操作できます。
これにより、コマンドの出力を取得したり、コマンドに入力を渡したりすることが可能です。
以下に、標準入出力の操作方法を詳しく説明します。
標準出力の取得
コマンドの標準出力を取得するには、capture_output=True
を指定します。
これにより、コマンドの出力をresult.stdout
で取得できます。
import subprocess
# lsコマンドを実行し、出力を取得
result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
# 実行結果を表示
print("標準")
print(result.stdout)
このコードを実行すると、カレントディレクトリのファイルリストが表示されます。
標準エラー出力の取得
コマンドの標準エラー出力を取得するには、stderr=subprocess.PIPE
を指定します。
これにより、エラー出力をresult.stderr
で取得できます。
import subprocess
# 存在しないコマンドを実行し、エラー出力を取得
result = subprocess.run(['nonexistent_command'], capture_output=True, text=True)
# エラー出力を表示
print("標準エラー")
print(result.stderr)
このコードを実行すると、エラーメッセージが表示されます。
標準入力の操作
コマンドに標準入力を渡すには、input
オプションを使用します。
以下の例では、echo
コマンドに文字列を渡しています。
import subprocess
# echoコマンドに標準入力を渡す
result = subprocess.run(['cat'], input='Hello, World!', capture_output=True, text=True)
# 実行結果を表示
print("標準")
print(result.stdout)
このコードを実行すると、Hello, World!
という文字列が表示されます。
標準入出力のリダイレクト
標準入出力をファイルにリダイレクトすることも可能です。
以下の例では、ls
コマンドの出力をファイルに保存しています。
import subprocess
# lsコマンドの出力をファイルにリダイレクト
with open('output.txt', 'w') as f:
subprocess.run(['ls', '-l'], stdout=f)
print("lsコマンドの出力がoutput.txtに保存されました。")
このコードを実行すると、カレントディレクトリのファイルリストがoutput.txt
に保存されます。
subprocess.run
を使用することで、外部コマンドの標準入出力を簡単に操作できます。
標準出力や標準エラー出力を取得したり、コマンドに入力を渡したりすることで、さまざまな用途に応じたプログラムを作成することが可能です。
実行結果の確認とエラーハンドリング
subprocess.run
関数を使用する際には、コマンドの実行結果を確認し、エラーが発生した場合に適切に対処することが重要です。
以下に、実行結果の確認方法とエラーハンドリングの手法を説明します。
実行結果の確認
subprocess.run
関数は、実行結果を含むCompletedProcess
オブジェクトを返します。
このオブジェクトには、以下の属性が含まれています。
returncode
: コマンドの終了コード。
0は成功、0以外はエラーを示します。
stdout
: コマンドの標準出力。stderr
: コマンドの標準エラー出力。
以下の例では、コマンドの実行結果を確認し、終了コードに基づいてメッセージを表示します。
import subprocess
# lsコマンドを実行
result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
# 実行結果の確認
if result.returncode == 0:
print("コマンドは成功しました。")
print("標準")
print(result.stdout)
else:
print("コマンドは失敗しました。")
print("標準エラー")
print(result.stderr)
エラーハンドリング
check
オプションを使用すると、コマンドが失敗した場合に自動的に例外が発生します。
これにより、エラーハンドリングが簡単になります。
以下の例では、check=True
を指定してコマンドを実行し、エラーが発生した場合に例外をキャッチします。
import subprocess
try:
# 存在しないコマンドを実行
result = subprocess.run(['nonexistent_command'], check=True, capture_output=True, text=True)
except subprocess.CalledProcessError as e:
print(f"エラーが発生しました: {e}")
print("標準エラー")
print(e.stderr)
このコードを実行すると、存在しないコマンドに対してエラーメッセージが表示されます。
エラーの詳細情報
CalledProcessError
例外には、エラーが発生したコマンドの情報が含まれています。
以下の属性を使用して、エラーの詳細を取得できます。
cmd
: 実行したコマンド。returncode
: 終了コード。output
: 標準出力。stderr
: 標準エラー出力。
以下の例では、エラーの詳細情報を表示します。
import subprocess
try:
# 存在しないコマンドを実行
result = subprocess.run(['nonexistent_command'], check=True, capture_output=True, text=True)
except subprocess.CalledProcessError as e:
print(f"コマンド: {e.cmd}")
print(f"終了コード: {e.returncode}")
print("標準エラー")
print(e.stderr)
subprocess.run
を使用する際には、実行結果を確認し、エラーが発生した場合に適切に対処することが重要です。
returncode
を確認することで成功・失敗を判断し、check
オプションを利用することでエラーハンドリングを簡素化できます。
これにより、より堅牢なプログラムを作成することが可能になります。
応用的な使い方
subprocess.run
関数は、基本的なコマンド実行だけでなく、さまざまな応用的な使い方が可能です。
ここでは、いくつかの応用例を紹介します。
複数のコマンドをパイプで接続
シェルのパイプ機能を利用して、複数のコマンドを接続することができます。
shell=True
を指定することで、シェルを介してコマンドを実行できます。
以下の例では、ls
コマンドの出力をgrep
コマンドでフィルタリングしています。
import subprocess
# lsコマンドの出力をgrepでフィルタリング
result = subprocess.run('ls -l | grep ".py"', shell=True, capture_output=True, text=True)
# 実行結果を表示
print("Pythonファイル:")
print(result.stdout)
環境変数の設定
env
オプションを使用すると、コマンドを実行する際の環境変数を設定できます。
以下の例では、MY_VAR
という環境変数を設定してコマンドを実行しています。
import subprocess
import os
# 環境変数を設定
my_env = os.environ.copy()
my_env['MY_VAR'] = 'Hello, World!'
# 環境変数を使用してechoコマンドを実行
result = subprocess.run(['echo', '$MY_VAR'], env=my_env, shell=True, capture_output=True, text=True)
# 実行結果を表示
print("環境変数の")
print(result.stdout)
非同期実行
subprocess.run
は同期的にコマンドを実行しますが、subprocess.Popen
を使用することで非同期にコマンドを実行することができます。
以下の例では、sleep
コマンドを非同期に実行し、他の処理を行っています。
import subprocess
import time
# 非同期にsleepコマンドを実行
process = subprocess.Popen(['sleep', '5'])
# 他の処理を行う
print("他の処理を実行中...")
time.sleep(2)
print("処理が完了しました。")
# コマンドの終了を待つ
process.wait()
print("sleepコマンドが完了しました。")
コマンドの出力をファイルに保存
コマンドの出力をファイルに保存することも可能です。
以下の例では、df
コマンドの出力をdisk_usage.txt
というファイルに保存しています。
import subprocess
# dfコマンドの出力をファイルに保存
with open('disk_usage.txt', 'w') as f:
subprocess.run(['df', '-h'], stdout=f)
print("ディスク使用状況がdisk_usage.txtに保存されました。")
コマンドの実行時間を計測
コマンドの実行時間を計測することもできます。
以下の例では、time
モジュールを使用してコマンドの実行時間を測定しています。
import subprocess
import time
# コマンドの実行開始時間を記録
start_time = time.time()
# sleepコマンドを実行
subprocess.run(['sleep', '3'])
# 実行時間を計測
end_time = time.time()
execution_time = end_time - start_time
print(f"コマンドの実行時間: {execution_time}秒")
subprocess.run
関数は、基本的なコマンド実行だけでなく、さまざまな応用が可能です。
複数のコマンドの接続、環境変数の設定、非同期実行、出力のファイル保存、実行時間の計測など、用途に応じて柔軟に活用することができます。
これにより、より高度なスクリプトやプログラムを作成することが可能になります。
よくあるエラーとその対処法
subprocess.run
を使用する際には、いくつかの一般的なエラーが発生することがあります。
ここでは、よくあるエラーとその対処法を紹介します。
FileNotFoundError
エラー内容: 指定したコマンドが見つからない場合に発生します。
対処法: コマンド名が正しいか、またはそのコマンドがシステムにインストールされているかを確認します。
パスが必要な場合は、フルパスを指定することも検討してください。
import subprocess
try:
# 存在しないコマンドを実行
result = subprocess.run(['nonexistent_command'], check=True)
except FileNotFoundError as e:
print(f"エラー: {e}")
CalledProcessError
エラー内容: check=True
を指定した場合、コマンドが非ゼロの終了コードで終了したときに発生します。
対処法: コマンドの引数や実行環境を確認し、エラーの原因を特定します。
stderr
を確認することで、エラーメッセージを取得できます。
import subprocess
try:
# 存在しないコマンドを実行
result = subprocess.run(['ls', 'nonexistent_file'], check=True, capture_output=True, text=True)
except subprocess.CalledProcessError as e:
print(f"エラーが発生しました: {e.stderr}")
TimeoutExpired
エラー内容: timeout
オプションを指定した場合、コマンドが指定した時間内に終了しなかったときに発生します。
対処法: コマンドの実行時間を見直し、必要に応じてtimeout
の値を調整します。
また、コマンドが長時間かかる理由を調査することも重要です。
import subprocess
try:
# 長時間実行されるコマンドを実行
result = subprocess.run(['sleep', '10'], timeout=5)
except subprocess.TimeoutExpired:
print("コマンドがタイムアウトしました。")
標準出力が空
エラー内容: コマンドが正常に実行されたが、標準出力が空である場合があります。
対処法: コマンドの引数やオプションを確認し、期待する出力が得られるように修正します。
また、コマンドが実行される環境や条件も確認することが重要です。
import subprocess
result = subprocess.run(['echo'], capture_output=True, text=True)
if result.stdout.strip() == '':
print("標準出力が空です。コマンドを確認してください。")
標準エラー出力の確認
エラー内容: コマンドが失敗した場合、標準エラー出力にエラーメッセージが表示されますが、これを見逃すことがあります。
対処法: コマンドの実行後にstderr
を確認し、エラーメッセージを表示するようにします。
これにより、問題の特定が容易になります。
import subprocess
result = subprocess.run(['ls', 'nonexistent_file'], capture_output=True, text=True)
if result.returncode != 0:
print("エラーが発生しました。")
print("標準エラー")
print(result.stderr)
subprocess.run
を使用する際には、さまざまなエラーが発生する可能性があります。
これらのエラーを理解し、適切に対処することで、より堅牢なプログラムを作成することができます。
エラーメッセージを確認し、原因を特定することが重要です。
他のsubprocess関数との比較
Pythonのsubprocess
モジュールには、subprocess.run
以外にもいくつかの関数が用意されています。
それぞれの関数には異なる用途や特徴があり、状況に応じて使い分けることが重要です。
ここでは、subprocess.run
と他の主要な関数との比較を行います。
subprocess.run vs subprocess.call
subprocess.run
: コマンドを実行し、CompletedProcess
オブジェクトを返します。
標準出力や標準エラー出力をキャプチャすることができ、エラーハンドリングも容易です。
subprocess.call
: コマンドを実行し、終了コードを返します。
標準出力や標準エラー出力をキャプチャする機能はありません。
シンプルな用途に適しています。
import subprocess
# subprocess.runの例
result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
print(result.stdout)
# subprocess.callの例
exit_code = subprocess.call(['ls', '-l'])
print(f"終了コード: {exit_code}")
subprocess.run vs subprocess.Popen
subprocess.run
: コマンドを実行し、完了するまで待機します。
シンプルで使いやすいですが、非同期処理には向いていません。
subprocess.Popen
: コマンドを非同期に実行し、プロセスオブジェクトを返します。
標準入出力のリダイレクトや、プロセスの管理が柔軟に行えます。
import subprocess
import time
# subprocess.runの例
subprocess.run(['sleep', '2'])
# subprocess.Popenの例
process = subprocess.Popen(['sleep', '2'])
print("他の処理を実行中...")
time.sleep(1)
print("処理が完了しました。")
process.wait()
subprocess.run vs subprocess.check_call / subprocess.check_output
subprocess.check_call
: コマンドを実行し、終了コードが0でない場合にCalledProcessError
を発生させます。
標準出力はキャプチャしません。
subprocess.check_output
: コマンドを実行し、標準出力をキャプチャして返します。
終了コードが0でない場合はCalledProcessError
を発生させます。
import subprocess
# subprocess.check_callの例
try:
subprocess.check_call(['ls', 'nonexistent_file'])
except subprocess.CalledProcessError as e:
print(f"エラーが発生しました: {e}")
# subprocess.check_outputの例
try:
output = subprocess.check_output(['ls', '-l'], text=True)
print(output)
except subprocess.CalledProcessError as e:
print(f"エラーが発生しました: {e}")
subprocess
モジュールには、さまざまな関数が用意されており、それぞれ異なる用途に適しています。
subprocess.run
は、シンプルで使いやすいコマンド実行のための関数ですが、他の関数も状況に応じて活用することで、より柔軟なプログラムを作成することができます。
目的に応じて適切な関数を選択し、効果的に利用しましょう。
実用例
subprocess.run
関数は、さまざまな実用的なシナリオで活用できます。
ここでは、いくつかの具体的な例を紹介します。
これらの例を参考にして、実際のプロジェクトに応じた使い方を考えてみましょう。
ファイルのバックアップ
特定のディレクトリ内のファイルをバックアップするために、tar
コマンドを使用する例です。
以下のコードでは、指定したディレクトリを圧縮してバックアップファイルを作成します。
import subprocess
import datetime
# バックアップするディレクトリ
source_dir = '/path/to/source_directory'
# バックアップファイル名
backup_file = f'backup_{datetime.datetime.now().strftime("%Y%m%d_%H%M%S")}.tar.gz'
# tarコマンドを使用してバックアップを作成
subprocess.run(['tar', '-czf', backup_file, source_dir])
print(f"バックアップが作成されました: {backup_file}")
システム情報の取得
df
コマンドを使用して、ディスクの使用状況を取得し、標準出力に表示する例です。
import subprocess
# dfコマンドを実行
result = subprocess.run(['df', '-h'], capture_output=True, text=True)
# 実行結果を表示
print("ディスク使用状況:")
print(result.stdout)
Webページのダウンロード
curl
コマンドを使用して、指定したURLからWebページをダウンロードする例です。
ダウンロードした内容はファイルに保存されます。
import subprocess
# ダウンロードするURL
url = 'https://www.example.com'
# 保存するファイル名
output_file = 'downloaded_page.html'
# curlコマンドを使用してWebページをダウンロード
subprocess.run(['curl', '-o', output_file, url])
print(f"Webページがダウンロードされました: {output_file}")
画像のリサイズ
ImageMagick
を使用して、画像をリサイズする例です。
以下のコードでは、指定した画像ファイルを指定したサイズにリサイズします。
import subprocess
# リサイズする画像ファイル
input_image = 'input_image.jpg'
output_image = 'output_image.jpg'
width = 800
height = 600
# convertコマンドを使用して画像をリサイズ
subprocess.run(['convert', input_image, '-resize', f'{width}x{height}', output_image])
print(f"画像がリサイズされました: {output_image}")
プロセスの監視
ps
コマンドを使用して、現在実行中のプロセスを監視し、特定のプロセスが実行中かどうかを確認する例です。
import subprocess
# 実行中のプロセスを確認
process_name = 'python3'
result = subprocess.run(['pgrep', process_name], capture_output=True, text=True)
if result.stdout:
print(f"{process_name} プロセスが実行中です。")
else:
print(f"{process_name} プロセスは実行されていません。")
これらの実用例は、subprocess.run
を使用してさまざまなタスクを自動化する方法を示しています。
ファイルのバックアップ、システム情報の取得、Webページのダウンロード、画像のリサイズ、プロセスの監視など、subprocess
モジュールを活用することで、Pythonスクリプトから外部コマンドを効果的に利用できます。
これらの例を参考にして、自分のプロジェクトに応じた使い方を考えてみましょう。
まとめ
この記事では、Pythonのsubprocess.run
関数を中心に、外部コマンドの実行方法やその活用法について詳しく解説しました。
subprocess
モジュールの基本的な使い方から、標準入出力の操作、エラーハンドリング、応用的な使い方、実用例まで幅広く取り上げ、実際のプログラムに役立つ情報を提供しました。
これを機に、subprocess
モジュールを活用して、日常のタスクを自動化したり、効率的に処理を行ったりすることに挑戦してみてください。