概要
Python の subprocess でコマンドを実行する方法ついて解説します。
subprocess.run
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None,
capture_output=False, shell=False, cwd=None, timeout=None,
check=False, encoding=None, errors=None, text=None, env=None,
universal_newlines=None, **other_popen_kwargs)
args で指定されたコマンドを実行します。
コマンドの指定方法
コマンドは引数も含めて文字列で指定する方法とコマンド及び引数をリストで指定する方法の2通りがあります。
文字列で指定する場合、shell=True
を指定します。
import subprocess
subprocess.run(["echo hoge"], shell=True)
CompletedProcess(args=['echo hoge'], returncode=0)
shell=True
を指定しないと、echo hoge
で1つのコマンドと解釈され、FileNotFoundError 例外が発生します。
subprocess.run(["echo hoge"])
# FileNotFoundError: [Errno 2] No such file or directory: 'echo hoge'
コマンド及び引数をリストで指定する場合は次のようになります。リストで指定するメリットとして、引数のエスケープが必要な場合に自動で行われることです。(例: ファイル名に空白が含まれる場合)
subprocess.run(["echo", "hoge fuga"])
CompletedProcess(args=['echo', 'hoge fuga'], returncode=0)
標準入力、標準出力、標準エラー出力
- stdin: 標準入力
- stdout: 標準出力
- stderr: 標準エラー出力
これらはプログラムの標準入力、標準出力、および標準エラー出力のファイルハンドルを指定します。stdin
、stdout
、stderr
には以下が指定できます。
- subprocess.PIPE: パイプ
- subprocess.DEBNULL: null デバイス (/dev/null)
- ファイルオブジェクト: open() などで作成したファイル記述子
- None: リダイレクトしない
encoding
またはerrors
を指定したか、text=True
を指定した場合、ファイルオブジェクトが指定されたstdin
、stdout
、stderr
はテキストモードで開かれます。stderr=subprocess.STDOUT
を指定した場合、標準エラー出力を標準出力にリダイレクトします。encoding
はファイルオブジェクトを開く際のエンコーディングを指定します。errors
はエンコードやデコードの際のエラーをどのように扱うかを指定します。stdin
において、\n
は行の区切り文字として扱われます。
制限時間を設定する
timeout を指定した場合、timeout
秒経過して処理が完了していない場合、子プロセスは kill され、TimeoutExpired
例外が送出されます。
try:
subprocess.run(["sleep", "5"], timeout=1)
except subprocess.TimeoutExpired as e:
print(e.cmd)
print(e.timeout)
print(e.output)
print(e.stdout)
print(e.stderr)
['sleep', '5'] 0.9999595480039716 None None None
プログラムが正常終了したかどうかを判定する
check=True
を指定した場合、実行したプロセスのリターンコードが0でない場合は CalledProcessError 例外を送出します。
try:
subprocess.run(["sleep"], check=True)
except subprocess.CalledProcessError as e:
print(e.cmd)
print(e.returncode)
print(e.output)
print(e.stdout)
print(e.stderr)
['sleep'] 1 None None None
結果を受け取る
文字列で受け取る
capture_output=True, text=True
を引数に指定します。結果は subprocess.run() の返り値の CompletedProcess オブジェクトの stdout、stderr 属性で取得できます。
ret = subprocess.run(["ls", "-la"], capture_output=True, text=True)
print("コマンド", ret.args)
print("リターンコード", ret.returncode)
print("標準出力", ret.stdout)
print("標準エラー出力", ret.stderr)
コマンド ['ls', '-la'] リターンコード 0 標準出力 total 16 drwxr-xr-x 2 root root 4096 Sep 4 07:19 . drwxr-xr-x 16 root root 4096 Sep 4 06:13 .. -rw-r--r-- 1 root root 7058 Sep 4 07:19 post.ipynb 標準エラー出力
ファイルに出力する
stout
にファイルオブジェクトを渡すと、標準出力をファイルに出力できます。標準エラー出力も同じファイルに出力したい場合は stderr=subprocess.STDOUT
を指定して、標準エラー出力を標準出力にリダイレクトします。
f = open("date.txt", "w")
ret = subprocess.run(["date"], stdout=f, stderr=subprocess.STDOUT)
入力を行う
以下のように2つの入力を要求されるプログラムがあった場合、与える入力を input
引数に指定できます。
文字列中の \n
は、手動で入力したときに Enter キーで1つの入力を完了されることに相当します。
add.py
x = int(input("x:"))
y = int(input("y:"))
print(x + y)
stdin = "1\n5"
ret = subprocess.run(["python", "add.py"], input=stdin, capture_output=True, text=True)
print(ret.stdout)
x:y:6
コメント