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


やりたいこと

  • Node-REDからPythonを実行する。

特徴

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

やりたいことイメージ


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

ゴール

1. Node-REDからpostgreSQLに接続してcsvファイルを作成する

必要なノードは5つ。下記ノードを下記の順番で結合する。
1) 【機能】function ノード
 - 目的:SQL文を組み立てる
 - 使用方法:msg.payloadにSQL文を直接記述

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ファイルのフルパスを指定する

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

return msg;

5) 【ストレージ】file ノード
 - 目的:csvファイルを作成する
 - 使用方法:ファイル名には空白を指定(空白の場合、msg.filenameへの設定値でファイルを作成)

2. Node-REDからbatファイルを実行する

必要なノードは2つ。下記ノードを下記の順番で結合する。

ポイント

  • 実行コマンドを任意に指定できるようにmsg.payloadにコマンド+引数を指定する(通常はexecノードにコマンドを直接指定するが、その場合可変に出来ない)
    ※execノードのコマンドへの設定値+空白+msg.payloadでコマンド実行していると思われる

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

functionノードへの記述イメージ
// 実行するbatファイルのフルパス 例)"C:\\temp\\conda\\ExecPython.bat" ※指定したPythonプログラムを実行するbatファイルの
msg.command = msg.execPythonCmd
// 第1引数 例)"test.py" ※実行するPythonプログラムのファイル名
msg.arg_1 = msg.execPythonNm
// 第2引数 例)実行するPythonプログラムへのI/F(入力ファイル)
msg.arg_2 = "indata\\" + msg.timestamp + ".csv"
// 第3引数 例)実行する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のチェックボックスはオン

3. batファイルにてconda環境を有効にしてPythonプログラムを実行する

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
activateConda.bat
conda activate [有効にしたい環境名 例)base]

4. PythonプログラムへのI/Fファイルを指定する

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)

実行

準備1)実行ファイル用意

3,4に記載のファイルを下記の通り格納する。

準備2)フロー作成

1,2に記載のフローを準備する。
下記のように、実行に必要な情報をfunctionノードに記載すると管理が楽かも。
※「injectノード→実行条件設定→1→2」の順番で実行するフローを作成

実行条件設定
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フォルダに出力

おわりに

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