python-venv node development history

# Introduction
　This is the English version of day 22 of the [Node-RED Advent Calendar 2024](https://qiita.com/advent-calendar/2024/node-red).

　Japanese Version:

 https://qiita.com/background/items/d2e05e8d85427761a609

　Last year, I wrote about [creating nodes for the Node-RED MCU](https://qiita.com/background/items/9b820251aa9dda5a3167).

　This year, I’ve also been working on developing several new nodes. Among them, I focused especially on the development of the python-venv node. As I’ll explain later, this node allows you to execute Python scripts in a Python virtual environment.

　When I first developed the node, I didn’t use Python much myself. However, I now use Python with the python-venv node, interact with people worldwide, and improve the node through ongoing development.
　In this article, I’ll cover an overview of the node, its development history, and some use cases.

▼GitHub repository is here.

https://github.com/404background/node-red-contrib-python-venv

▼The page in the Node-RED flow library is here

https://flows.nodered.org/node/@background404/node-red-contrib-python-venv

# Node Mechanism
## Overview
　This node creates a Python virtual environment, installs packages into it, and executes Python code.
　When you install node-red-contrib-python-venv, the following nodes are added: the venv node, the pip node, and the venv-exec node.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/6604390b-3b82-fd47-ac85-6ce308ae4607.png)
 
　You can write and execute Python code in the venv node as shown below. It’s like a Python version of the function node in Node-RED.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/033d3ec9-6225-476d-e05f-9a00d72678a4.png)
 
　In the image below, the pip packages in the virtual environment are different from those in the system pip. This gives the node a unique level of independence.
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/4248fba0-6966-75b3-631c-3969d5955612.png)
　The pip node allows you to document the package installation process. By sharing the flow, you can reconstruct the Python execution environment.

　The internal workings of the node primarily rely on the following mechanisms:
- Specifying paths within the Python virtual environment to utilize it.
- Retrieving absolute paths of the code to be executed.
- Running preinstall scripts via the npm install command.

### Python Virtual Environment

　While developing desktop applications with Electron, I wanted to use a Python virtual environment without executing the activate script. 
　After exploring the virtual environment structure and official documentation, I realized that specifying paths would suffice. This mechanism is employed in the node.
Related Article：[Pythonの仮想環境を作成する（venv、Windows）](https://404background.com/program/python-venv/)

### Absolute Path

　In JavaScript, you can use __dirname, and in Python, you can use \_\_file\_\_ to retrieve absolute paths. The path to the created virtual environment is stored in a .json file, which can be accessed by both JavaScript and Python.
Related Article：[Node-REDのノードを作成してみる　その１（python-venv）](https://404background.com/program/node-create-python-venv/)

### package.json Scripts

　Using the npm scripts feature, we execute the script to create the virtual environment.
　By specifying commands under the preinstall field in the scripts section of package.json, the commands are executed before npm install is run.
Official Documentation：https://docs.npmjs.com/cli/v8/using-npm/scripts

# Development History

　The development of this node has been conducted openly on GitHub. Writing everything in English helped me interact with international developers.

　The first version of the node was released around March this year. I remember developing it during my spring break. Details about the initial implementation are written in the article below:
　[Node-REDのノードを作成してみる　その１（python-venv）](https://404background.com/program/node-create-python-venv/)

　The initial version executed commands using the execSync method from the Node.js child_process module.

　Around June, I received a pull request from an overseas developer that enabled the node to access the Node-RED msg object. I had been unsure how to implement this feature, so their contribution was greatly appreciated.

 https://github.com/404background/node-red-contrib-python-venv/pull/6

　Now, you can access msg.payload or msg.test in Python, as shown below:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/cf594495-0950-4589-c97a-3495b1ef56e4.png)

　I also added a configuration node that allows the creation of multiple virtual environments.

 https://github.com/404background/node-red-contrib-python-venv/pull/15

　You can choose a virtual environment in the node, install packages, and execute code within that environment.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/37506440-8fd2-8d38-a0f8-6a5a729c15a8.png)

　Packages installed with npm commands are added to the node_modules folder in the execution directory, but you can also specify absolute paths to create virtual environments in other directories.

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/0b6add29-bccb-8ed0-d7d8-e06e91285f27.png)

　There was also a time when I added multi-line text editor functionality in the morning, and by afternoon, an improved pull request enhanced it further for Python-specific use cases. Development progressed rapidly.

https://github.com/404background/node-red-contrib-python-venv/pull/11

　In July, someone proposed using the spawn method from the child_process module, inspired by the python-shell node. Unlike execSync, this enabled features like stopping execution, sequential output, and displaying execution states.

https://github.com/404background/node-red-contrib-python-venv/pull/20

　For example, you can sequentially output processes in a while loop. While this can also be done using the inject node, it can now be achieved with the venv node.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/464bcac9-8595-7901-5620-4b7af9983186.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/e5ce6509-2f81-ea5a-77c5-75438555dc86.png)

　In October, I added a new node called the venv-exec node.

https://github.com/404background/node-red-contrib-python-venv/pull/32

　For example, if you install Whisper or gTTS using pip, you can run these commands directly in the node. The venv-exec node enables this functionality.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/70d82e36-1177-6801-be46-25f2c1443178.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/86c0f1f5-c9e6-4276-8006-e210cec93705.png)

　However, it still cannot stop execution mid-process or output sequentially, leaving room for improvement.

# Use Cases

## Utilizing Python Packages
　Being able to execute Python means you can leverage powerful Python packages.

　For instance, I created a flow to control a simple robot using voice commands with a microcontroller.

<iframe width="560" height="315" src="https://www.youtube.com/embed/EH8wNS8ryJ4" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

　The overall flow looks like this:
Related Article：[音声でロボットを操作してみる（Node-RED、Gemma2、Faster Whisper、XIAO ESP32C3）](https://404background.com/program/voice-operate/)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/5ecf2173-c1e3-4cfb-6774-b7f07f36847e.png)

　The venv node is used to transcribe audio recorded by a microphone into text. I also used the ollama node to interact with a local LLM.
Related Article：[Ollamaを使ってみる　その１（Gemma2、Node-RED）](https://404background.com/program/ollama/)

　Text sent to the local LLM is generated using the template node, allowing AI to perform conditional judgments.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/8e40964f-92fd-e75d-0881-a048dc0d8558.png)

　The transcription takes about 2 seconds, and processing with the local LLM takes another 2 seconds, so it’s not suitable for real-time processing. However, it works well for tasks like moving a robotic arm to a specified position.

## Generating Code with ChatGPT

　With generative AI capable of creating code, the venv node pairs well with AI.

　In the following flow, a PDF of a research paper is processed to extract text, translate it, and summarize it using a local LLM.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616003/5186051e-70f4-b20e-cdbc-493709f7f8e3.png)

　For large documents, the output of the venv node couldn’t be passed as input directly. Therefore, the data was temporarily saved to a file and processed node by node.
　While it’s possible to have ChatGPT generate all the code as a single script, dividing it into nodes makes the flow easier to modify and manage.

## Running on Raspberry Pi

　Although I don’t have a concrete example, I’ve had discussions with ChatGPT about development on Raspberry Pi, and Python code was often suggested.
　The python-venv node works on Raspberry Pi, allowing you to utilize Python resources available on the platform.
　However, some operating systems may cause errors. For instance, if Python 2 is the default version or if venv and pip are not pre-installed on Ubuntu, additional setup is required.

## Connecting with Unreal Engine 5

　As described in my Day 21 article of the [Node-RED Advent Calendar 2024](https://qiita.com/advent-calendar/2024/node-red), it’s possible to integrate with Unreal Engine 5 (UE5).
　By enabling the continuous execution mode in the venv node, you can sequentially output YOLO detection results and send them using the HTTP Request node. This data can be used to control objects in UE5 by converting 2D coordinates from two viewpoints into 3D coordinates.

<iframe width="560" height="315" src="https://www.youtube.com/embed/3VK54l226DA" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

　Additionally, using Pixel Streaming, you can stream the UE5 screen and capture it with the venv node to execute YOLO. While YOLO training can be executed with commands, you can also use the venv-exec node to achieve this.
Related Article：[YOLOで物体検出　その２（Python、Node-RED）](https://404background.com/program/yolo-2/)
[Unreal Engine 5を使ってみる　その11（Pixel Streaming ）](https://404background.com/ue5/unreal-engine-5-11/)
<iframe width="560" height="315" src="https://www.youtube.com/embed/lJGo7YjbGmk" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>


# Conclusion

　With the python-venv node, you can execute Python in Node-RED without affecting the system Python environment.
　Thanks to the collaboration of international contributors, features I couldn’t implement on my own were realized. I plan to continue improving the node step by step.

　Finally, I would like to express my gratitude to all the contributors. Thank you, contributors!
　If you encounter any issues, have suggestions, or questions, feel free to contact me on the [GitHub repository](https://github.com/404background/node-red-contrib-python-venv)!