Pythonで別コマンド・別プロセスを実行したい時によく使うsubprocessについて、使用頻度の高い用法をサンプルコード付きでまとめてみました。
1. 基本形
基本はsubprocess.run(<コマンド>)
という形で実行します。
コマンドはlist型で指定します。
(例えばls -l
は、["ls", "-l"]
と指定)
import subprocess
# ls -lを実行
cmd = ["ls", "-l"]
subprocess.run(cmd)
2. 結果取得
終了コード
終了コードは、subprocess.run()の返り値から取得できます。
subprocess.run()を実行すると、CompletedProcess
が返されるのですが、
この返り値のreturncode
属性にコマンドの終了コードが格納されています。
import subprocess
# ls -lを実行
cmd = ["ls", "-l"]
result = subprocess.run(cmd)
# 終了コードは返り値の.returncodeに格納されている
print("returncode={}".format(result.returncode))
# > returncode=0
標準出力/標準エラー出力
コマンドの結果出力(標準出力/標準エラー出力)を取得したい場合は、capture_output=True
を指定します。
テキストとして取得する場合はtext=True
を合わせて指定しておくと便利です。
(text=Trueを指定しない場合はbytes型で返されます)
import subprocess
cmd = ["ls", "-l"]
# capture_output=True, text=Trueを指定
result = subprocess.run(cmd, capture_output=True, text=True)
# .stdoutに標準出力、.stderrに標準エラー出力が格納される
print(result.stdout)
print(result.stderr)
3. 例外処理
終了コードが0以外の時に例外を起こす
終了コードが0以外の時に例外を起こしたい場合は、check=True
を指定します。
0以外の場合にsubprocess.CalledProcessError
の例外が発生します。
import subprocess
try:
cmd = ["ls", "/hoge/fuga"]
# check=Trueを指定
result = subprocess.run(cmd, check=True)
except subprocess.CalledProcessError as e:
# 終了コードが0以外の場合、例外が発生
print(e)
# > Command '['ls', '/hoge/fuga']' returned non-zero exit status 1.
コマンドをタイムアウトさせる
コマンドをタイムアウトさせたい場合はtimeout
パラメータを指定します。
タイムアウトした場合、subprocess.TimeoutExpired
の例外が発生し、コマンド(子プロセス)はkill(kill -9)されます。
import subprocess
try:
cmd = ["sleep", "10"]
# timeout=<秒数>を指定
result = subprocess.run(cmd, timeout=3)
except subprocess.TimeoutExpired as e:
# タイムアウトした場合、例外が発生
# コマンド(子プロセス)はkill(kill -9)される
print(e)
# > Command '['sleep', '10']' timed out after 2.999830309 seconds
4. その他
shellのワイルドカード(*)やパイプ(|)を使う
*や|を使いたい場合は、shell=True
を指定します。
この時、コマンドは文字列として指定しないと想定通りの動作にならないので注意です。
import subprocess
# コマンドは一つの文字列として指定
cmd = "ps aux | grep python3"
# shell=Trueを指定
result = subprocess.run(cmd, shell=True)
※shell injectionの脆弱性が発生しないように気をつけましょう。
標準入力を渡す
標準入力を使用したい場合は、input
パラメータを指定します。
標準出力の時と同様で、テキストを扱う場合はtext=True
を指定しておくと便利です。
import subprocess
cmd = ["tr", "-d", "x"] # 標準入力から指定の文字("x")を削除するコマンド
# inputに標準入力として渡したい文字列を指定。バイナリで指定する場合はtext=Trueは不要
result = subprocess.run(cmd, input="xyz", text=True)
コメント