【Node-RED】Node-REDからAnaconda仮想環境上のPythonを実行する【Anaconda】【Python】

# やりたいこと
- Node-REDからPythonを実行する。

# 特徴
- （Python実行環境を容易にするため）Anacondaを使用する
- （初学者のハードルを低くするため）可能な限り入手可能なNode-REDノードを活用する

# やりたいことイメージ
<img width="425" alt="イメージ.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35883/9cb9b971-d47d-8268-b7e7-8f398cc0a587.jpeg">
1. Node-REDからpostgreSQLに接続してcsvファイルを作成する
2. Node-REDからbatファイルを実行する
3. batファイルにてconda環境を有効にしてPythonプログラムを実行する
4. PythonプログラムへのI/Fファイルを指定する

### 実行環境
- OS:windows 10
- postgreSQL：9.6
- ANACONDA NAVIGATOR：1.9.12
- Python(Anaconda仮想環境上)：3.7.7
- Node-RED：v1.0.4

### ゴール
<img width="425" alt="完成イメージ.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35883/23d46398-f201-6b78-ee69-6fd99dd6b8d8.jpeg">

# 1. Node-REDからpostgreSQLに接続してcsvファイルを作成する
必要なノードは５つ。下記ノードを下記の順番で結合する。
1) 【機能】function ノード
　- 目的：SQL文を組み立てる
　- 使用方法：msg.payloadにSQL文を直接記述

``` javascript:functionノードへの記述イメージ
msg.select = "SELECT  val"
msg.from = "FROM public.sensordata "
msg.where = "where sensor ='湿度センサー'"
msg.orderBy = "order by datetime desc"
msg.limit = "limit 1000"

msg.payload = msg.select
msg.payload += " " + msg.from
msg.payload += " " + msg.where
msg.payload += " " + msg.orderBy
msg.payload += " " + msg.limit

return msg;
```

2) 【ストレージ】postgres ノード
　- 目的：postgreSQLに接続して、SQLを実行する
　- 使用方法：標準的な使い方
3) 【機能】json to csv converter ノード
　- 目的：postgre ノードがjson形式で返すのでcsv形式に変換する
　- 使用方法：標準的な使い方
4) 【機能】function ノード
　- 目的：ファイル名を指定する
　- 使用方法：msg.filenameにcsvファイルのフルパスを指定する

``` javascript:functionノードへの記述イメージ
// 例）msg.rootpath = "C:\\temp\\conda"
// 例）msg.timestampはinjectノードから取得
msg.filename = msg.rootpath + "\\indata\\" + msg.timestamp + ".csv";

return msg;
```
5) 【ストレージ】file ノード
　- 目的：csvファイルを作成する
　- 使用方法：ファイル名には***空白***を指定（空白の場合、msg.filenameへの設定値でファイルを作成）
<img width="395" alt="fileノード.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35883/e910530a-01df-0204-049d-997b070c6ddd.jpeg">

# 2. Node-REDからbatファイルを実行する
必要なノードは２つ。下記ノードを下記の順番で結合する。
### ポイント
- 実行コマンドを任意に指定できるように***msg.payloadにコマンド＋引数を指定***する（通常はexecノードにコマンドを直接指定するが、その場合可変に出来ない）<br>※execノードのコマンドへの設定値＋空白＋msg.payloadでコマンド実行していると思われる

1) 【機能】function ノード
　- 目的：実行コマンドを組み立てる
　- 使用方法：msg.payloadに実行するコマンドを設定

```javascript:functionノードへの記述イメージ
// 実行するbatファイルのフルパス　例）"C:\\temp\\conda\\ExecPython.bat"　※指定したPythonプログラムを実行するbatファイルの
msg.command = msg.execPythonCmd
// 第１引数　例）"test.py"　※実行するPythonプログラムのファイル名
msg.arg_1 = msg.execPythonNm
// 第２引数　例）実行するPythonプログラムへのI/F（入力ファイル）
msg.arg_2 = "indata\\" + msg.timestamp + ".csv"
// 第３引数　例）実行するPythonプログラムへのI/F（出力ファイル）
msg.arg_3 = "outdata\\" + msg.timestamp + ".csv"

msg.payload = msg.command + " " + msg.arg_1 + " " + msg.arg_2 + " " + msg.arg_3

return msg;
```
2) 【機能】exec ノード
　- 目的：コマンドを実行する
　- 使用方法：***コマンドには空白***を指定。***msg.payloadのチェックボックスはオン***。
<img width="388" alt="execノード.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35883/957cd9cd-eddd-165c-7c66-d2554003b568.jpeg">

# 3. batファイルにてconda環境を有効にしてPythonプログラムを実行する
```bash:ExecPython.bat
rem 実行フォルダに移動
rem 例）C:\temp\conda 配下に実行環境が整備済の場合
cd /d C:\temp\conda

rem condaを有効にする
call activateConda.bat

rem Pythonを実行する
rem %1:実行するPythonのファイル名
rem %1～7:実行するPythonへの引数
python %1 %2 %3 %4 %5 %6 %7
```

```bash:activateConda.bat
conda activate [有効にしたい環境名　例）base]
```
# 4. PythonプログラムへのI/Fファイルを指定する
```python:test.py
import sys
# 引数を取得する
args = sys.argv

import pandas as pd
sensordata = pd.read_csv(args[1])

print(sensordata.describe())
sensordata.describe().to_csv(args[2], index=True)
```
# 実行
## 準備１）実行ファイル用意
３，４に記載のファイルを下記の通り格納する。
<img width="271" alt="フォルダ構成.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35883/309ddb5d-5767-cc22-92be-0b293a365b03.jpeg">
## 準備２）フロー作成
１，２に記載のフローを準備する。
下記のように、実行に必要な情報をfunctionノードに記載すると管理が楽かも。
※「injectノード→実行条件設定→１→２」の順番で実行するフローを作成

```python:実行条件設定
msg.timestamp = msg.payload
msg.rootpath = "C:\\temp\\conda"
msg.execPythonCmd = "C:\\temp\\conda\\ExecPython.bat"
msg.execPythonNm = "test.py"
return msg;
```

## 実行結果
indataフォルダに格納されたcsvファイルを読み取り、簡単な統計情報をoutdataフォルダに出力
<img width="335" alt="実行結果.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35883/088200c5-1a12-e4db-7847-acc417144743.jpeg">

# おわりに
IoTのプラットフォームとしては「Node-RED」、データサイエンスのプラットフォームとしては「Anaconda+Python+JupyterNotebook」
が挙げられるかと思いますが、これらがシームレスにつながるとDXが進むんじゃないかと期待してます。