subprocessモジュールを使って子プロセスにデータを送ったり、結果を受け取ったりする

このまえ、os.system関数で外部コマンドを実行するやり方を書いたけど、どうもsubprocessモジュールを使うやり方のほうが新しいらしい。subprocessモジュールの Popenクラスを使うと、子プロセスにデータを送ったり、結果を受け取ったりできる。

cf. http://docs.python.jp/2.7/library/subprocess.html

まずは、結果を受け取る方法から。

import subprocess

p = subprocess.Popen("ls *.py", stdout=subprocess.PIPE)
files = p.communicate()[0].split("\r\n")
for file in files:
    print file

subprocess.Popenオブジェクトを作るには、第1引数にコマンドを指定する。結果を受け取るにはstdout=subprocess.PIPE を指定しておく。で、communicateメソッドで結果を取得する。

実行結果:

^o^ > python test_subprocess.py
argv.py
bubble_sort.py
count_files.py
counting_sort.py
csv_read.py
csv_write.py
default_arg.py
dict.py
dict_keys.py
dictionary.py
enumerate.py
exception1.py
exception2.py
exception3.py
false.py
fib.py

(以下略)

次に、子プロセスにデータを渡す方法。supbrocess.Popenオブジェクトを作るときに、stdin=subprocess.PIPEを指定しておいて、communicateメソッドの引数としてデータを渡す。

import subprocess

p = subprocess.Popen("python file_input.py", stdin=subprocess.PIPE)
data = open("sample.txt", "r").read()
p.communicate(data)

実行結果:

^o^ > python test_subprocess2.py
<stdin> 1 : Mon
<stdin> 2 : Tue
<stdin> 3 : Wed
<stdin> 4 : Thu
<stdin> 5 : Fri
<stdin> 6 : Sat
<stdin> 7 : Sun

期待通りの出力が得られた。

最後に両方をやってみよう。

import subprocess

p = subprocess.Popen("python file_input.py", stdin=subprocess.PIPE, stdout=subprocess.PIPE)
data = open("sample.txt", "r").read()
output = p.communicate(data)[0]
for line in output.split("\r\n"):
    print line

実行結果:

^o^ > python test_subprocess3.py
<stdin> 1 : Mon
<stdin> 2 : Tue
<stdin> 3 : Wed
<stdin> 4 : Thu
<stdin> 5 : Fri
<stdin> 6 : Sat
<stdin> 7 : Sun

上のと同じ出力だけど、これは子プロセスから結果を受け取ったPythonスクリプトが出力したもの。