Learning 1 documentation

subprocess

«  select   ::   Contents   ::   sys  »

subprocess

はじめに

subprocessの目的は、以下のモジュールを置き換えることです。

  • os.system
  • os.spawn*
  • os.popen*
  • popen2.*
  • commands.*

commands

subprocess.getoutputで置き換えることができます。 ただし、これは互換性を保つためのものなので、 check_outputを使用してください。

出力を関数の戻り値にする場合

関数check_outputを使用します。

out = subprocess.check_output(["ls", "-l"])

これは、Popenを簡略した書き方です。

実際は

popen = subprocess.Popen(["ls", "-l"], stdout=subprocess.PIPE)
out = popen.communicate()[0]

と同じ結果になります。

Warning

出力が何も無いとエラーが返ってきます。

subprocess.check_output("ls |grep abc")
#CalledProcessError
#non-zero exit status 1

universal_newlines=Trueにした場合は、 出力をテキストとして扱います。 そのため、出力結果がdecodeされます。

os.systemの代わりの関数を自作するのであれば

def system(cmd):
 return subprocess.check_output(cmd, shell=True, universal_newlines=True)

となります。

シェルを利用する

コマンドを実行します。この関数は、os.systemを拡張です。

subprocess.call(["ls", "-l"])

コマンドが成功した場合は0を返します。

エラーが返ってきた場合の処理

subprocess.check_call関数を使用します。

try:
   subprocess.check_call(["ls", "a"])  # -aのハイフンが抜けてます
except CalledProcessError:
   sys.exit(1)

pipe

複数のコマンドを連ねたパイプを実装します。

#ls -a | grep .py
ls = subprocess.Popen(["ls", "-a"], stdout=subprocess.PIPE)
grep = subprocess.Popen(["grep", ".py"], stdin=ls.stdout, stdout=subprocess.PIPE)

stdoutにPIPEを指定しないと、結果がディスプレイに出力されてしまいます。

正直、僅かなコマンドを書くのに、これだけの記述は面倒し分かりにくいです。その場合

from subprocess import check_out

out = check_out("ls -a | grep .py", shell=True).decode("utf-8")

とすれば、比較的簡単に記述ができます。

Popenオブジェクト

Popenで返すオブジェクトは以下の属性を持ちます。

  • communicate
  • pid
  • poll
  • send_signal
  • terminate
  • kill
  • wait
  • returncode

また、ファイルオブジェクトも持ち合わせています。

  • stdin
  • stdout
  • stderr

communicate

子プロセスと対話する

p = Popen(["cat"], stdin=PIPE, stdout=PIPE)
p.stdin.write("hoge\n")
os.read(p.stdout.fileno(), 1024)
#p.readline()

writeとreadを繰り返すことで、対話することが可能です。

p.communicateを使えとマニュアルには書いてあるが、それを使うと1回やり取りした時点でfdを閉じてしまうから2回目で「ValueError: I/O operation on closed file」

«  select   ::   Contents   ::   sys  »

inserted by FC2 system