Pythonで標準入力を受け取る

Pythonスクリプト間で標準入出力を使ってデータのやり取りをしてみる。

まずは標準入力を受け取る方法。sys.stdin.read()を使う。

$ cat stdin.py
#!/usr/bin/env python

import sys

stdin_str = sys.stdin.read()
print stdin_str

$ echo -n test | ./stdin.py
test

Pythonのスクリプト内で別のPythonスクリプトを呼び出すときの標準入出力

先の例では標準入力はshell上から渡したが、Pythonのスクリプト内で別のPythonスクリプトを呼び出し、そのときに標準出力を与える方法を書く。

$ cat call_other.py
#!/usr/bin/env python

import os
import subprocess

other_script = os.path.join(os.path.abspath(os.path.dirname(__file__)), "stdin.py")

proc = subprocess.Popen(other_script, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
stdout_str = proc.communicate("test")[0]

print stdout_str

$ ./call_other.py
test

subprocess.PIPEで標準入出力先にパイプが繋がるようになる。subprocesscommunicate()の引数に文字列を渡すことで自身のスクリプトから標準出力を外部プログラムへ渡すことができ、また外部プログラムの標準出力もcommunicate()の戻り値のはじめの要素から得られる。

ちなみにcommunicate()の戻り値は(stdout_data, stderr_data)なので、stderr=subprocess.PIPEsubprocess.Popen()で設定していれば、戻り値の二つ目の要素から標準エラー出力が得られる。

Python 3系の場合の標準入出力

Python 3系の場合はcommunicateの引数、戻り値ともにencode, decodeしなければならない。あるいはencodingを指定して読み込む。さらにContext Managerがサポートされているのでwithを使う。

encode, decodeを使う場合

other_script = os.path.join(os.path.abspath(os.path.dirname(__file__)), "stdin.py")

with subprocess.Popen(other_script, stdin=subprocess.PIPE, stdout=subprocess.PIPE) as proc
  stdout_str = proc.communicate("test".encode())[0].decode()

encodingを指定する場合

other_script = os.path.join(os.path.abspath(os.path.dirname(__file__)), "stdin.py")

with subprocess.Popen(other_script, stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding="utf-8") as proc
  stdout_str = proc.communicate("test")[0]