標準入出力を使おうという話

ひととおり C++OCaml やらでちょっと重めのプログラムを書いて、さて Web 経由で公開しちゃうぞとか思うと、はてどうやって JavaRubyPerl から呼び出していいものかというはなしが出てきて、外部プロセスは重い(特に係数データを読み込んだりすると)、libXXXX はたるい、localhost に通信はだるい。現実的には libXXX なんですが、ohkura に「ライブラリがセグフォると、プロセスごと落ちるよ」といわれて、それもいかんなぁということになりました。OCaml でライブラリ作る気になれんし。

そこで標準入出力を使いましょうということです。標準入出力が使えない言語なんてない!(たぶん) 要は、50万棋譜のときにやったのと同じで、1行入力したら1行出力するようなプログラムにしておく。あるいは、1入力単位を読み込んだら、それに対する1出力単位を出力する。全部読まないで処理するのがポイント。そして、呼び出し元のスクリプト言語からプロセス作って、標準入力にデータを流して標準出力からデータを読み込む。これだけ。エラーが起きたら(おそらく落ちたため)、一度殺して、プロセス再起動。簡単かつ堅牢です。中断処理とかしたくなると標準入力の監視スレッドを作ったりと、少しめんどいですが、極端なはなしプロセスごと殺して再起動すればいいですし。


適当な例。最近 Python も書けるようになった。

import subprocess

class Echo:
    def __init__(self):
        self.proc = subprocess.Popen('cat', stdin = subprocess.PIPE, stdout = subprocess.PIPE)

    def call(self, str):
        self.proc.stdin.write(str + '\n')
        self.proc.stdin.flush()
        return self.proc.stdout.readline()

echo = Echo()
print(echo.call("hogehoge"))
print(echo.call("fugafuga"))

cat コマンドが echo として振る舞うという寸法だ。プロセスは一つしか作らない。引数があるときは、適当にエンコードすれば OK。