dak ブログ

python、rubyなどのプログラミング、MySQL、サーバーの設定などの備忘録。レゴの写真も。

pythonia による node.js からの python の関数の実行

2022-04-16 15:19:27 | Node.js
pythonia で使うことで、node.js (TypeScript) から python の関数を実行することができます。

■python プログラム (list.py)
def list_sum(lst):
    s = 0
    for val in lst:
        s += val
    return s

def list_mul(lst):
    m = 0
    for i, val in enumerate(lst):
        if i == 0:
            m = val
        else:
            m *= val
    return m

■TypeScript プログラム
import process from 'process';
import { python } from 'pythonia';

(async () => {
  const list = await python('./list.py'); // ./ が必要
  const lst = [1, 2, 4, 6, 8];

  const s = await list.list_sum(lst);
  console.log(s);

  const m = await list.list_mul(lst);
  console.log(m);

  process.exit(0);
})();

■実行結果
加算、乗算の計算結果が得られます。
21
384

ただし、以下のエラーメッセージが出力されます。
Exception ignored in: <function Proxy.__del__ at 0x7f404f6e7f70>
...
SystemExit: 1

node.js からの python プログラム実行

2022-04-16 12:24:25 | Node.js
Python-Shell を使って、node.js (TypeScript) から python のプログラムを実行する方法のメモ。

Python-Shell では node.js から python のメソッドを直接呼び出すわけではなく、
別プロセスで python プログラムを実行し、標準入出力で python プログラムとやりとりします。

今回は、以下のようなプログラムを作成してみました。
・python プログラム
 標準入力から1行読み込み、空白区切りで行を分割し、合計値を計算します。
 例: "1 2 3" => 6

・TypeScript プログラム
 空白区切りの数字文字列を python プログラムに送り、結果を取得して表示します。

■python プログラム
行毎に flush しないと、python 側で無限に結果待ちの状態となります。
import sys
import re
import json

def proc_record(res, line):
    line = re.sub('[\r\n]+$', '', line)
    items = re.split('[ ]+', line)
    res['result'] = sum([int(item) for item in items])

def main():
    for line in sys.stdin:
        res = {
            'status': 0,
            'message': 'OK',
            'result': None,
        }

        try:
            proc_record(res, line)
        except Exception as e:
            res['status'] = 1
            res['message'] = 'error'
        finally:
            print(json.dumps(res, ensure_ascii=False))
            sys.stdout.flush()

    return 0

if __name__ == '__main__':
    res = main()
    exit(res)

■TypeScript プログラム
import { PythonShell } from 'python-shell';

async function recv(pysh: PythonShell): Promise<any> {
  return new Promise((resolve) => {
    pysh.on('message', (msg) => {
      resolve(msg);
    });
  });
}

(async () => {
  const pysh = new PythonShell('sum.py');

  pysh.send('1 2 3');
  const res1 = await recv(pysh);
  console.log(res1);

  pysh.send('1 3 5');
  const res2 = await recv(pysh);
  console.log(res2);

  pysh.end(() => {});
})();

■実行結果
{"status": 0, "message": "OK", "result": 6}
{"status": 0, "message": "OK", "result": 9}