npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rosepetal/node-red-contrib-python-executor

v1.1.0

Published

A Node-RED node for executing Python code, similar to the function node but for Python

Readme

node-red-contrib-python-executor

Python into your Node-RED flows with a node that feels familiar, stays friendly, and keeps things fast when you need it.

Example

What You Get

  • Run small Python snippets whenever a message arrives.
  • Reuse your favorite Python tools without leaving Node-RED.
  • Choose between quick start-up or high-speed processing.
  • See clear status updates so you always know what is happening.

Before You Start

  • Install Python 3 on the machine running Node-RED.
  • Know where your Python interpreter lives (for most systems it is python3).

Node Options

  • Name – Optional label that appears on the canvas.
  • Python Path – The command Node-RED should run (for example python3 or a full path if you use a virtual environment).
  • Timeout – How long to wait for Python to finish before giving up. Useful to stop code that gets stuck.
  • Python Code – Your script. It always receives a message named msg, and whatever you return is passed along.
  • Hot Mode – Keeps Python processes running between messages for faster responses.
  • Workers – How many hot workers to run in parallel (only appears when Hot Mode is on). Use more workers when you expect bursts of messages.
  • Preload Imports – Optional lines that run once when each hot worker starts. Handy for heavier libraries you do not want to import on every message.

Cold vs Hot Mode

  • Cold Mode (default) – Starts a fresh Python process for every message. Great for occasional runs or quick experiments.
  • Hot Mode – Keeps a pool of Python workers ready. Messages are handled much faster after the first one. Best for frequent or time-sensitive flows.

Typical Flow

  1. Drop the python executor node into your flow.
  2. Connect an Inject node (input) and a Debug node (output).
  3. Add a short script, for example:
    msg['payload'] = f"Hello, {msg.get('payload', 'world')}!"
    return msg
  4. Deploy and trigger the flow. Adjust options as needed.

Context & Warnings

You can read/write Node-RED context from Python and emit warnings:

count = flow_ctx.get("count", 0)
flow_ctx.set("count", count + 1)
node.warn(f"count is now {count + 1}")
return msg
  • Use flow_ctx for flow context and global_ctx for global context.
  • Context values should be JSON-serializable.

Working with Images

Rosepetal images travel as a dict {data, width, height, channels, colorSpace, dtype}. Two helpers are injected into every node automatically — no import or boilerplate — so you can round-trip through OpenCV/NumPy:

import cv2

img = rp_to_cv(msg["payload"])          # -> BGR uint8 ndarray, ready for cv2
img = cv2.GaussianBlur(img, (7, 7), 0)
msg["payload"] = rp_from_cv(img, like=msg["payload"])
return msg
  • rp_to_cv(obj) returns a NumPy array. RGB/RGBA inputs are reordered to BGR/BGRA (OpenCV's convention); grayscale stays 2-D. It honors colorSpace and dtype, and accepts data as raw bytes, a Node Buffer, a list, or base64.
  • rp_from_cv(arr, like=obj) returns a Rosepetal image dict. The array is assumed BGR and reordered back to RGB. Pass the source dict as like= to preserve its colorSpace label.
  • data comes back as raw bytes, so it rides the shared-memory fast path in hot mode (no base64 bloat).
  • Both helpers work in hot and cold mode. Library imports do not: cold mode starts a fresh interpreter per message, so import cv2 belongs at the top of your code and Preload Imports applies to hot mode only. Re-importing numpy + OpenCV costs roughly 100 ms per message, so use hot mode for image work.

Benefits At A Glance

  • Familiar: Works just like the standard function node, only in Python.
  • Flexible: Supports both simple scripts and larger libraries.
  • Fast: Hot mode cuts response time dramatically for repeat work.
  • Clear: Status messages and notifications help you see what is working and what needs attention.
  • Binary Friendly: Hot workers stream large Buffers through shared memory instead of JSON, so images and other blobs stay fast.

Handling Large Binary Payloads

  • Hot workers stream Buffers to Python as raw bytes inside the worker's binary frame protocol, so image data never touches JSON or base64 and never hits the filesystem.
  • Python can return bytes, bytearray, or memoryview; they come back the same way and Node converts them to Buffers automatically. This also applies in cold mode.
  • The optimization is automatic—just enable hot mode when you expect heavy binary traffic.
  • Set ROSEPETAL_PY_INLINE_MAX_BYTES=<bytes> in Node-RED's environment to route buffers at or above that size through a /dev/shm file instead of the pipe (measured slower on Linux, but available if your platform prefers it).

Performance Notes (hot mode)

The hot path is built to stay off Node-RED's event loop and to cost as little as possible per message:

  • One binary frame per direction (u32 length | JSON header | raw blobs). Nothing is base64-encoded, no temporary files are written, and the user code is shipped to each worker once and cached by id.
  • The message is walked once, copy-on-write, so a message without Buffers costs zero allocations before JSON.stringify.
  • Nothing awaits: for a normal message the whole Node side of a round trip is synchronous work of a few microseconds; there are no promises created per key or per value.
  • Node status updates are coalesced (at most one every 50 ms per node) so the editor websocket and Status nodes are not flooded at high message rates. The texts are unchanged: hot: running, hot: 3ms, hot: ready.
  • Workers start with glibc malloc thresholds pinned (MALLOC_MMAP_THRESHOLD_, MALLOC_TRIM_THRESHOLD_, MALLOC_TOP_PAD_) so multi-megabyte image buffers are reused from the heap instead of being page-faulted in on every message. Set ROSEPETAL_PY_MALLOC_TUNING=0 to disable, or set the variables yourself to override.
  • rp_to_cv / rp_from_cv use cv2.cvtColor for the RGB↔BGR swap when OpenCV is installed (about 100x faster than the NumPy reversed view on a 720p frame; identical bytes).
  • print() inside hot-mode code goes to the worker's stderr (visible in the Node-RED log) and can no longer corrupt the worker protocol.

Typical round trips measured on a laptop (Node-RED → Python → Node-RED, one worker): a small dict in ~0.1 ms, a 200-item JSON payload in ~0.5 ms, a 16 KB buffer in ~0.13 ms, a 1280×720 RGB image through rp_to_cv/rp_from_cv in ~3 ms. The remaining floor for tiny messages is the two process wake-ups of a pipe round trip; on a machine with the powersave CPU governor those wake-ups are noticeably slower than with performance.

Enjoy mixing Python logic into your Node-RED projects without extra fuss. When you are ready for more performance, flip on Hot Mode and keep building.