サブプロセスしたい(subprocess)
1import subprocess
2subprocess.run(コマンド)
3subprocess.run(["ls", "-l"])
Pythonのスクリプトの中でシェルコマンドなどを使う場合、subprocessモジュールを使います。 実行するコマンドは引数やオプションも含めてリスト型で指定できます。
注釈
古いos.systemやsubprocess.call、subprocess.Popenを直接使う書き方も存在しますが、
現在はsubprocess.runを使うのが推奨されています。
戻り値のオブジェクトを通じて、実行結果、標準出力、エラーなどをまとめて扱えます。
実行結果を確認したい
1result = subprocess.run(["ls", "-l"], capture_output=True, text=True)
2
3type(result) # CompletedProcess
4result.args
5result.returncode
6result.stdout
7result.stderr
subprocess.runの戻り値はCompletedProcessオブジェクトです。
戻り値を変数に代入すれば、このオブジェクトを通じて実行結果を確認できます。
capture_outputオプション、textオプションを有効にすると、
標準出力や標準エラー出力に表示された内容を確認できます。
注釈
text=Trueを指定しないと、result.stdout、result.stderrはbytes型で返ってきます。
文字列(str)として扱いたい場合はtext=Trueを指定してください
例外処理したい(CalledProcessError)
1import subprocess
2
3try:
4 result = subprocess.run(コマンド, check=True)
5except subprocess.CalledProcessError as e:
6 print(f"Error: {e}")
checkオプションを有効にすると、コマンドが失敗したときに例外を発生させることができます。
subprocessはCalledProcessErrorという例外クラスを持っています。
シェル経由で実行したい(shell=True)
1subprocess.run("ls -l | grep py", shell=True)
shell=Trueを指定すると、パイプ(|)やリダイレクト(>)のような
シェル機能を含む文字列コマンドをそのまま実行できます。
注意
shell=Trueは、コマンドの一部にユーザー入力をそのまま含めると、
シェルインジェクションの脆弱性につながります
(例:f"ls {user_input}"のような組み立て方)。
ユーザー入力を扱う場合は、shell=Trueを避け、
冒頭のようにコマンドをリスト型で渡す書き方を使ってください。
標準入力したい(input)
1result = subprocess.run(["grep", "py"], input="foo.py\nbar.txt\n", text=True, capture_output=True)
2result.stdout
inputオプションで、コマンドの標準入力にデータを渡せます。
text=Trueと組み合わせることで、文字列のまま渡せます。
タイムアウトしたい(timeout)
1import subprocess
2
3try:
4 subprocess.run(["sleep", "10"], timeout=3)
5except subprocess.TimeoutExpired as e:
6 print(f"Timeout: {e}")
timeoutオプションで、コマンドの実行時間の上限を秒数で指定できます。
上限を超えるとTimeoutExpired例外が発生し、プロセスは自動的に終了させられます。
ハングする可能性のある外部コマンドを呼び出す場合は、設定しておくと安全です。