NodeRed node for interacting with Python3 scripts.
node-red-contrib-py3run/data/python in your container and store runner.py therepy3run node to your flow. Put a function node in front of it to craft the required payload. Or use the node inputs to pass path and args.Passing no arguments to Python is possible as well. Simply leave msg.payload.args or the corresponding input empty.
The path to the Python script cannot be empty.
js
msg = {
payload: {
path: "/data/python/sample.py",
args: {
"a": 1,
"b": 2
}
}
}
return msg;
`Python
Put your Python script in any location you want (change it in msg.payload.path accordingly). I'd recommend to use a subfolder in /data (like /data/python) and make sure it's mounted to the host system. The script needs to follow a simple structure:`py
function name must be run
function must take exactly one argument
payload which holds the arguments passed from NodeRed
def run(payload: dict) -> list:
# Extract values by accessing the key name you used in the payload
a = payload.get("a")
b = payload.get("b")
# Do some basic checks to make sure your data has the correct type / format
if not a or not b:
# Error, therefore return None for stdout and an error message for stderr
return [None, "Either a or b is missing"]
elif type(a) not in [float, int] or type(b) not in [float, int]:
# Error, therefore return None for stdout and an error message for stderr
return [None, "Either a or b is not numeric"]
# return your result in stdout and None for stdout.
return [a+b, None]
`If you wanna get rid of checking the input types, you can use the __types object in your custom script to map your argument names to a desired type. The runner will check the types at runtime by trying to cast the incoming values to the type if the desired type and incoming type are mismatching. If it fails, you'll get a message on stderr and the script won't run.
`py
object name must be __types
object must contain a key (the name of your argument) and the desired type.
__types = {
"a": int,
"b": int
}same as in first example
def run(payload: dict) -> dict:
a = payload.get("a")
b = payload.get("b")
# But without further checks since runner will check for int or try to cast.
# Be aware, passing floats to this script will lead to wrong results since they will be converted to int
return [a+b, None]
`Python modules
It is possible to get pip3 running in a NodeRed container, but it's not recommended though.
- Run bash as root inside the container: docker exec -u root -it
- Install py3-pip via apk: apk install py3-pip
- Switch back to normal user: su node-red or docker exec -it
- Install any module you want: pip3.10`> Not every library might work, especially if there are dependencies to any linked libraries (like libvosk.so for the vosk module)