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()

あわせて読みたい

プログラミング学習に興味がある方は、まずは無料体験会へ

無料体験会・お申し込みはこちら