Help us understand the problem. What is going on with this article?

[Python2.7] subprocess の使い方まとめ

More than 3 years have passed since last update.

概要

subprocessを使う機会が結構多いので、わからなくて調べた点をまとめます。
調査時の自分のユースケースとしてPython 2.7環境が前提だったため、本記事はPython 2.7向けになります。

基本的には以下の公式ドキュメントを参照して下さい。
17.1. subprocess — サブプロセス管理 — Python 2.7.x ドキュメント

特にPython3.5以上の場合は汎用のrun()コマンドが追加されていたりと使用方法が異なっているため、
そのまま転用せず公式を参照して下さい。
17.5. subprocess — サブプロセス管理 — Python 3.5.2 ドキュメント

インポート指定

import
import subprocess

基本的なAPI

subprocess.call

・実行時の標準出力/標準エラーは実行されたタイミングで出力される
・正常時も異常時もリターンコードを返す

実行サンプル
import subprocess

print '!!! start'

cmd = 'echo aaa'
retcode = subprocess.call(cmd.split())
print retcode

cmd = 'false'
retcode = subprocess.call(cmd.split())
print retcode

print '!!! end'
出力
aaa
!!! start
0
1
!!! end

subprocess.check_call

・実行時の標準出力/標準エラーは実行されたタイミングで出力される
・正常時にはリターンコード0を返す
・異常時には subprocess.CalledProcessError 例外を送出する

実行サンプル
import subprocess

print '!!! start'

cmd = 'echo aaa'
retcode = subprocess.check_call(cmd.split())
print retcode

cmd = 'false'
try:
    retcode = subprocess.check_call(cmd.split())
except subprocess.CalledProcessError as e:
    print e.returncode
    print e.cmd
    print e.output

print '!!! end'
出力
aaa
!!! start
0
1
['false']
None
!!! end

subprocess.check_output

・実行時の標準出力/標準エラーは実行されたタイミングで出力される
・正常時には標準出力を返す
・異常時には subprocess.CalledProcessError 例外を送出する

実行サンプル
import subprocess

print '!!! start'

cmd = 'echo aaa'
d = subprocess.check_output(cmd.split())
print d,

cmd = 'unexist_command'
try:
    d = subprocess.check_output(
            cmd.split(),
            stderr=subprocess.STDOUT,
            shell=True)
    print d,
except subprocess.CalledProcessError as e:
    print e.returncode
    print e.cmd
    print e.output,

print '!!! end'
出力
!!! start
aaa
127
['unexist_command']
/bin/sh: unexist_command: command not found
!!! end

subprocess.check_output 使用時に標準エラーを取得する

以下のように、stderr=subprocess.STDOUT を指定する。

使用例
    d = subprocess.check_output(
            cmd.split(),
            stderr=subprocess.STDOUT,
            shell=True)

subprocessの実行ディレクトリを変更する

cwd オプションの使用

実行ディレクトリの指定
subprocess.call(cmd, cwd=workdir)

実行例を以下に示す。

実行サンプル
import subprocess

d1 = subprocess.check_output(['pwd'])                   # 初期位置 /tmp
d2 = subprocess.check_output(['pwd'], cwd='/tmp/hoge')  # 絶対パスでの確認
d3 = subprocess.check_output(['pwd'])                   # 他の移動の影響は受けない
d4 = subprocess.check_output(['pwd'], cwd='./hoge')     # 相対パスでの確認

print 'case 1:'
print d1,
print d2,

print 'case 2:'
print d3,
print d4,
実行例
case 1:
/tmp
/tmp/hoge
case 2:
/tmp
/tmp/hoge

python subprocess changing directory - Stack Overflow

注意点

実行コマンドを外部から取り込む場合、特に shell=True を指定している場合は、コマンド注入攻撃をされる場合が想定されるため、セキュリティには十分注意すること

補足:コマンド注入攻撃 / Shell Injection

IPA ISEC セキュア・プログラミング講座:Webアプリケーション編 第6章 入力対策:コマンド注入攻撃対策
Code injection - Wikipedia

不明な動作

check_outputshell=Trueを指定した場合に、標準出力/標準エラーが取得できない場合がある。(空文字列が返る)

参考

Python の subprocess で出力を受け取るときは communicate() を使おう - Qiita
pythonでコマンド実行するには - それマグで!

koara-local
言語は最近は C#, Javaあたりがメイン。端末VimからIDEに移行。IntelliJすごい。Qiitaでの記事やその中の主張は、所属している企業/団体の意見を代表するものではありません。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away