Node-REDのfunctionノードだけで解決が難しいときにフロー内にPythonの処理を導入する

Node-REDを使用していると、偶にこのPythonの処理をそのまま埋め込めればいいのになと思うことがあります。

自分も以前のエントリでwordcloudの画像生成に関して拡張ノードがなかったのでexecノードを使用して回避したことがありました。

参考

uepon.hatenadiary.com

このときには、モジュールがコマンドラインCLI)で実行できるようになっていたので、その方法が良かったのかもしれないなと思ったのですが、いろいろ調べてみるとpythonのコード記述ができるpython-functionノードというものがあるとわかりました。今回はそれの使い方について見てみようと思います。

拡張ノードのインストール

今回使用する拡張ノードはnode-red-contrib-python-functionという名前です。

flows.nodered.org

このノードのドキュメントにもありますが以下の注意点があるようです。

(注意)保証されるものではないのでプロダクトでは使用しないのは前提となります。

In any case, this quick hacked node will let you write functions using Python instead of Javascript! How cool is that? Too cool to be used in production, that is for sure.

(注意)非同期的なプロセスに関しても保証はされません(スレッドなど)

Python is by default a synchronous runtime. The function is run in a dedicated child process, therefore it won't block the NodeJS main process, but in any case only 1 message is processed at a time. That is, of course, unless you use any of the concurrency features available in Python, like multithreading, multiprocessing, Tornado, Twisted...

なんとなくわかるような内容です。このモジュールですが、Pythonの2系3系どちらにも対応しているようなのですが、現状3系を使用したほうがいいかなと思います(どうやってバージョンを判別しているのだろうか?)

では、いつもどおりメニューから拡張ノードのインストールを行いましょう。メニューの【パレットの管理】からインストール作業を行いますが、特にトラブルなく処理は終わると思います。

f:id:ueponx:20220228224934p:plain

f:id:ueponx:20220228224937p:plain

f:id:ueponx:20220228224939p:plain

パレットの【機能】のカテゴリの中にpython-functionノードが追加されていればOKです。

f:id:ueponx:20220228225036p:plain

python-functionノードをつかってみる

基本ノードに含まれるfunctionノードとそれほど大きな差異はないようです。入力エリアにPythonのコードを入力していくだけです。importも動作可能なので必要なモジュールがあれば、使用することもできそうです。(venv系の動作はやめておいたほうがいいかも?)

簡単な実験を行うためのフローを作成します。以下のノードを配置して行きます。

  • injectノード
  • python-functionノード
  • debugノード

f:id:ueponx:20220228225348p:plain

python-functionノードをダブルクリック処理を記述していきます。

f:id:ueponx:20220228225402p:plain

例えば下記のようなコードを動作させることができます。

import os

k = 0
for x in range(10**6):
    k += x

# 作業フォルダを取得
folder_name = os.getcwd()

# msgオブジェクトに格納(文字列でないとエラーがでるようです)
msg["folder_name"] = folder_name
msg["payload"] = str(k)

return msg

今回はdebugノードで【対象】をmsgオブジェクト全体を表示するように変更しておきます。

f:id:ueponx:20220228225634p:plain

作成したフロー

f:id:ueponx:20220228225537p:plain

このノードの処理の結果がある場合には、msgオブジェクト(dictionary)として返す必要があるので、結果などを文字列として格納する必要がありそうです。msg.payload以外にも値を格納できますが値をString型に変更しておきます。

実行結果

f:id:ueponx:20220228225823p:plain

python-functionノードを使用することでNode-RED上にPythonのコードを内包することは可能となりますが、デバッグなどの容易さを考えるのであればPythonCLIのプログラムを作成したほうが楽なのではないかと思います。execノードからそのプログラムを呼び出し、標準出力やエラー出力をうまく調整しても似た処理はできるかなと思います。もしメリットがあるとするならばフローで出てきたパラメータ使用するのが楽?かも。changeノードexecノードを使えばそれも解決しますが。

おわりに

今回はNode-RED側からPythonのコードを記述して処理を行うpython-functionノードを使用してみました。

基本的にはあまりおすすめできる感じではないのですが、ちょっとしたPythonの動きを確認するのであればこちらを拡張ノードをつかうのもありかもしれません。

最近はPythonのモジュールがNode.js側に移植されている処理も多くなってきているので、そこまでの需要はあるのかなと思いますが、何かあったときには実験的につかってみるのもありかもしれません。

/* -----codeの行番号----- */