2025-11-18 11:02:39 +01:00
2025-11-18 11:02:39 +01:00
2025-11-18 11:02:39 +01:00
2025-11-18 11:02:39 +01:00
2025-11-18 11:02:39 +01:00
2025-11-18 11:02:39 +01:00
2025-11-18 11:02:39 +01:00
2025-11-18 10:58:51 +01:00
2025-11-18 11:02:39 +01:00
2025-11-18 11:02:39 +01:00
2025-11-18 11:02:39 +01:00
2025-11-18 11:02:39 +01:00
2025-11-18 11:02:39 +01:00
2025-11-18 11:02:39 +01:00

Python Binding for Node.js

Description

This project enables seamless integration of a Python backend with a Node.js application by maintaining a persistent Python subprocess. It allows calling Python methods asynchronously from Node.js using a dynamic JavaScript class interface, supports setting and getting Python-side properties, and enables receiving streamed partial results from long-running Python operations.

How to Use

JavaScript Usage Example

import ChatModel from "./python_bindings.js";

async function runExample() {

	const chat = new ChatModel({ model: "something" });

	// Set properties dynamically
	await chat.setProperty("model", "something");
	await chat.setProperty("tokenizer", 123);

	// Get properties from Python backend
	const modelResponse = await chat.getModelPath();
	console.log(modelResponse);     // { Model: "something" }

	const tokenizerResponse = await chat.getTokenizer();
	console.log(tokenizerResponse); // { Tokenizer: 123 }

	// Call Python methods asynchronously
	let response = await chat.increment({ by: 5 });
	console.log("Incremented counter:", response.counter);

	response = await chat.increment({ by: 2 });
	console.log("Incremented counter:", response.counter);

	response = await chat.increment({ by: 2 });
	console.log("Incremented counter:", response.counter);

	// Listen for streamed partial results
	chat.onMessage(function(data) {
		console.log("Streamed data:", data);
	});

	// Call method that streams partial results
	await chat.testStream();

	// Cleanly terminate Python subprocess
	chat.end();
}

runExample();

How to Write the Python Controller

The Python controller defines the backend logic and exposes methods callable from Node.js. It should extend the provided BaseController class and implement any methods you want to call from Node.js.

Controller Structure Example

# python/controller.py

import time
from baseController import BaseController

class Controller(BaseController):

	model     = None
	tokenizer = None
	counter   = 0

	def getModelPath(self, params):
		return {"Model": self.model}

	def getTokenizer(self, params):
		return {"Tokenizer": self.tokenizer}

	def increment(self, params):
		self.counter += params.get("by", 1)
		return {"counter": self.counter}

	def reset(self, params):
		self.counter = 0
		return {"counter": self.counter}

	def testStream(self, params):
		for i in range(5):
			time.sleep(0.5)
			self.send({"partial": f"step {i+1} complete"})
		return {"counter": self.counter}

Important Details

  • Inheritance: Your controller must inherit from BaseController.
  • Methods: Each method takes a single params dictionary argument containing parameters passed from Node.js.
  • Return Value: Methods return a JSON-serializable dictionary as a response.
  • Streaming: Use self.send(data) within methods to send partial streaming data back to Node.js. The JavaScript side will receive these via the registered stream callback.
  • Properties: Define class properties to maintain state accessible from both Python and Node.js via dynamic setProperty and getProperty calls.

Summary

  • Extend the Python Controller class to implement your backend logic.
  • Methods receive parameters and return JSON-serializable results.
  • Use self.send() to stream intermediate results when needed.
  • From Node.js, call these methods via the binding class, passing parameters as objects and receiving results asynchronously.
  • The binding handles JSON serialization, communication, and a persistent Python process lifecycle.

This design allows flexible and efficient integration between Node.js and Python for complex applications.

Description
This project provides a Python binding layer for Node.js that enables a persistent Python subprocess to be controlled through a dynamic JavaScript class interface. Node.js code can asynchronously call Python methods, set and retrieve Python-side properties, and receive streamed partial results from long-running operations, all via JSON-based message passing. By maintaining state inside the Python controller and exposing it through a simple API, the binding allows efficient, low-latency integration of Python logic—such as models, data processing, or computation pipelines—directly into Node.js applications without repeated process startup overhead.
Readme MIT 40 KiB
Languages
JavaScript 80.6%
Python 19.4%