d4c4ccfc180f26690f0a4bee8dcac291c21803dd
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
paramsdictionary 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
setPropertyandgetPropertycalls.
Summary
- Extend the Python
Controllerclass 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.
Languages
JavaScript
80.6%
Python
19.4%