You have a python script diagnosis.py
that generates realtime event-based data. Using Node.js, you can launch it as a child process and capture its output and then using Socket.IO emit that to the client and present it using HTML.
Server
var util = require('util'),
spawn = require('child_process').spawn,
ls = spawn('python', ['diagnosis.py']);
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen(80);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.sockets.on('connection', function (socket) {
ls.stdout.on('data', function (gdata) {
socket.emit('news', gdata.toString());
});
});
Client
<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script>
var d = "";
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
d += data;
document.getElementById('data').innerHTML = d;
console.log(data);
});
</script>
</head>
<body>
<div id="data"></div>
</body>
</html>
Question
This is great and all, but what if you're looking for the same HTML-Node.js communicative power that Socket.IO provides but instead between Node.js and Python? How would you do that? There's no web server there, so Socket.IO does not make a lot of sense and communicating over bare TCP does not provide the same power/elegance. How do I achieve full duplex communication between Node.js and Python?
Update I answered my own question, but I'm open to an alternative approach. RPC doesn't quite do what I want though.
Apache Thrift is a pretty awesome way to write RPC code between all of the major languages. You write a generic Thrift spec declaring the types and services, and then the code generator creates bindings for your desired languages. You can have apis for calling methods between your node and python code bases.
On a more generic low level approach, ZeroMQ is a message queue library that also has support for all of the major languages. With this, you can design your own solution for how you want to communicate (not just purely RPC). It has patterns for request/reply, push/pull, pub/sub, and pair. It gives you enough tools to put together a scalable system of any type.
I have used both and they are great solutions.
Just as a very rough example, the Thrift spec may be something like this. Lets say you want to communicate events from python to node.js, have it processed and get back some response:
myspec.thrift
struct Event {
1: string message;
}
service RpcService {
string eventOccurred(1:Event e)
}
This defines a data structure called Event
with a single string member to hold the message. Then a service called RpcService
define one function called eventOccured
which expects an Event
as an argument, and will return a string.
When you generate this code for python and node.js, you can then use the client side code for python and the server side code for node.js
python
from myrpc import RpcService, ttypes
# create a connection somewhere in your code
CONN = connect_to_node(port=9000)
def someoneClickedSomething():
event = ttypes.Event("Someone Clicked!")
resp = CONN.eventOccurred(event)
print "Got reply:", resp
node.js
// I don't know node.js, so this is just pseudo-code
var thrift = require('thrift');
var myrpc = require('myrpc.js');
var server = thrift.createServer(myrpc.RpcService, {
eventOccurred: function(event) {
console.log("event occured:", event.message);
success("Event Processed.");
},
});
server.listen(9000);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With