Python subprocess.check_output()とは?コマンドの出力を取得する方法
Pythonのsubprocess.check_output()は、外部コマンドを実行して標準出力を受け取る関数です。
失敗すると例外になるため、「成功した結果だけが欲しい」ときに簡潔に書けます。
subprocess.check_output()の基本的な使い方
import subprocess
out = subprocess.check_output(["echo", "hello"])
print(repr(out), type(out).__name__)
実行結果:
b'hello\n' bytes
戻り値はバイト列です。ここが最初のつまずきどころになります。
text=Trueで文字列にする
import subprocess
out = subprocess.check_output(["echo", "hello"], text=True)
print(repr(out))
実行結果:
'hello\n'
text=Trueを付けると文字列で返ります。付けないとout == "hello\n"がFalseになり、原因が分からず悩むことになります。
日本語が文字化けするときはencoding="utf-8"を明示してください。
末尾に改行が付いている点にも注意が必要です。値として使うなら.strip()を忘れないでください。
import subprocess
name = subprocess.check_output(["whoami"], text=True).strip()
print(f"ユーザー名: [{name}]")
失敗すると例外になる
import subprocess
try:
subprocess.check_output(["ls", "/no/such/dir"], stderr=subprocess.DEVNULL)
except subprocess.CalledProcessError as e:
print(type(e).__name__ + ":", e)
print(" output:", repr(e.output))
実行結果:
CalledProcessError: Command '['ls', '/no/such/dir']' returned non-zero exit status 1.
output: b''
check_call()と違い、例外から出力を取り出せます(ここでは空ですが、途中まで出ていれば入ります)。
標準エラー出力は入らない
重要な性質です。check_output()が受け取るのは標準出力だけで、エラーメッセージは含まれません。
エラー出力も欲しいときはstderr=subprocess.STDOUTで統合します。
import subprocess
r = subprocess.run(["ls", "/no/such"], stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, text=True)
print(repr(r.stdout))
実行結果:
'ls: /no/such: No such file or directory\n'
逆に、エラー出力を混ぜたくないならstderr=subprocess.DEVNULLで捨ててください。何も指定しないと、エラーが画面に流れます。
実践例|コマンドの結果を値として使う
import subprocess
branch = subprocess.check_output(
["git", "rev-parse", "--abbrev-ref", "HEAD"], text=True
).strip()
print("現在のブランチ:", branch)
「コマンドを実行して、その出力を変数に入れる」——シェルスクリプトの$(...)に相当する書き方です。
import subprocess
files = subprocess.check_output(["ls"], text=True).splitlines()
print("ファイル数:", len(files))
複数行の出力はsplitlines()でリストにすると扱いやすくなります。
run()での書き換え方
import subprocess
# 古い書き方
out = subprocess.check_output(["echo", "hello"], text=True)
# 新しい書き方
r = subprocess.run(["echo", "hello"], capture_output=True, text=True, check=True)
out = r.stdout
実行結果:
'hello\n'
行数は増えますが、できることが増えます。
| やりたいこと | check_output() |
run() |
|---|---|---|
| 標準出力を取る | できる | できる |
| 標準エラーを別に取る | できない | できる |
| 終了コードを見る | 例外経由のみ | returncode |
| 失敗しても続ける | できない | check=False |
stdoutとstderrを分けて扱いたいならrun()一択です。エラーの原因をログに残したいときに効きます。
4つの関数の使い分け
| 関数 | 戻り値 | 失敗時 |
|---|---|---|
call() |
終了コード | 例外にならない |
check_call() |
常に0 | 例外 |
check_output() |
標準出力 | 例外 |
run() |
CompletedProcess |
指定次第 |
check_output()は「出力が欲しい+失敗は例外」の組み合わせです。この用途に限れば今でも簡潔で、1行で書けるのが利点です。
注意点
- コマンドはリストで渡す(文字列は
FileNotFoundError) - コマンド不在は
FileNotFoundError(CalledProcessErrorではない) shell=Trueに外部の値を混ぜない(コマンドインジェクション)- 出力が巨大だとすべてメモリに載る——逐次処理するなら
Popenへ - 応答が返らないコマンドに備えて
timeoutを付ける
大量の出力を1行ずつ処理したいときは「Python subprocess.Popen()とは?プロセスを細かく制御する方法」を参照してください。
subprocess.check_output()のまとめ
check_output()は標準出力を受け取る関数- 戻り値はバイト列。文字列にするには
text=True - 末尾に改行が付くので
.strip()する - 失敗すると
CalledProcessError - 標準エラー出力は入らない。統合するなら
stderr=subprocess.STDOUT run(cmd, capture_output=True, check=True).stdoutと同じ- stdoutとstderrを分けたいなら
run()


