Python-shellの使い方

#1.目的

Node.js上で動作するJavascripコードからPythonコードを呼び出す。またPythonコードの出力をJavascriptコードが受け取り、受け取ったデータをJavascript上で処理したい。

![1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/2979fa1d-5577-f751-b2b8-9b7f8f2a324d.jpeg)


#2.手段

Python-shellを使います。[Python-shellのソースはこちら](https://www.npmjs.com/package/python-shell)



#3.環境設定、インストール

Python-shellを使うための事前準備やインストール方法を説明します。
node.jsとpythonは既にインストール済とします。

環境
・ubuntu 18.04 on Raspberry pi4　(Docker)
・node.js   v12.14.0
・npm       6.13.4


## 3-1 インストール方法

npmを使用してpython-shellをインストールする。

```console:
root@24f85fb6fd69:/home# npm install python-shell
npm WARN home@1.0.0 No description
npm WARN home@1.0.0 No repository field.

+ python-shell@1.0.8
updated 1 package and audited 103 packages in 2.37s
found 0 vulnerabilities
```


## 3-2 使用例

ディレクトリTESTを作り、下記のコードが記載されたtest.jsとsample.pyを配置する。

![2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/1b1f81d4-d6b8-980e-0ed4-e7a7c07e1541.jpeg)






```javascript:/home/pi/test/test.js
var {PythonShell} = require('python-shell');

//PythonShellのインスタンスpyshellを作成する。jsから呼ぶ出すpythonファイル名は'sample.py'
var pyshell = new PythonShell('sample.py');  

//jsからpythonコードに'5'を入力データとして提供する 
pyshell.send(5); 
 
//pythonコード実施後にpythonからjsにデータが引き渡される。
//pythonに引き渡されるデータは「data」に格納される。
pyshell.on('message', function (data) {
  console.log(data);
});
```


```python:/home/pi/test/sample.py
import sys
data = sys.stdin.readline()  #標準入力からデータを取得する
num=int(data)

def sum(a):
    return a+3

print(sum(num)) #print()の内容がjsに引き渡される。
```

## 3-3 実行

```python:/home/pi/test/
root@24f85fb6fd69:/home/test# node test.js  //test.jsを実行する
8    //pythonで処理をされた結果がjavascriptに引き渡され実行される。
```

![3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/304a597d-cc28-e461-710a-c561bd5abfdf.jpeg)


## 4 Javascript→PythonにJSONデータを送る場合

[Python-shellのソース](https://www.npmjs.com/package/python-shell)に従いトライしてみましたが、いたるところでJSON形式エラー「unexpected token T in json at position 1」が出力され、うまくいかずトレースするもPython-shellに関する情報もほとんどないようです。
そこで、別途作成したJSONファイルを介してJavascriptからPythonにJSONデータを送るようにしたところ、うまくいきました。

下記にコードを掲載します。


![15.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/d6f829aa-c3d3-3837-3ff6-1bab16078621.jpeg)


```javascript:/home/pi/test/test.js
  const PYPATH="sample.py"

  var {PythonShell} = require('python-shell');
  var pyshell = new PythonShell(PYPATH, { mode: 'text'}); //modeは「JSON]ではなく「text」を指定するのがよい。

 //(1-1)登録する銘柄データを辞書型配列に格納する。
  var obj={
    stock_num: 2145,
    c_name:"ABC_COMPANY",
    eps:100
  }

  //(1-2)辞書型配列をJSON形式に変換している。
  var jsondat = JSON.stringify( obj );

  //(1-3)上記jsondatを書き込むファイルがすでに存在する場合は当該ファイルを一度削除する。
  if (fs.existsSync(JSONFILEPATH)) fs.unlinkSync(JSONFILEPATH)  
  //(1-4)上記jsondatを書き込むファイルがすでに存在する場合は当該ファイルを一度削除する。
  fs.writeFileSync(JSONFILEPATH,jsondat) 


  //(2)jsからpythonコードに空データを送る。pythonコードを起動させるため
  pyshell.send(""); 

  //(4)Pythonの実行結果を受け取る
  pyshell.on('message',  function (data) {
          console.log(data)
          res.send({
          message: "success"   //pythonで実施した演算結果をフロントエンドに返している。
        })
      })
```


```python:/home/pi/test/sample.py
import sys
import json

#(3-1)JSONファイルtest.jsonを開く
f = open('test.json', 'r')
#(3-2)test.jsonのデータを読み取る
json_dict = json.load(f)
#(3-3)JSONデータjson_dictのkey:'stoch_num'にアクセスする。
dat1=json_dict['stock_num']
print(dat1) #printの内容をpython-shellに返却する
```

```json:/home/pi/test/test.json
{"stock_num":"2145","c_name":"ABC company","eps":"100"}
```