Python中的代码,在Node.js和Socket.IO中进行通信,呈现在HTML中

你有一个python脚本diagnosis.py生成基于事件的实时数据。 使用Node.js,你可以启动它作为一个subprocess,并捕获它的输出,然后使用Socket.IO发送到客户端,并使用HTML呈现它。

服务器

 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()); }); }); 

客户

 <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> 

这真是太好了,但是如果你正在寻找与Socket.IO提供的相同的HTML-Node.js通信能力,而是在Node.js和Python之间呢? 你会怎么做? 这里没有networking服务器,所以Socket.IO没有什么意义,通过裸TCP进行通信并不能提供相同的function/优雅。 如何实现Node.js和Python之间的全双工通信?

在这里输入图像描述

更新我回答了我自己的问题,但我打开另一种方法。 虽然RPC并不完全符合我的要求。

Apache Thrift是在所有主要语言之间编写RPC代码的非常好的方法。 你写一个通用的Thrift规范来声明types和服务,然后代码生成器为你想要的语言创build绑定。 您可以使用apis来调用节点和Python代码库之间的方法。

在更通用的低级方法中, ZeroMQ是一个消息队列库,也支持所有主要语言。 有了这个,你可以devise你自己的解决scheme,你想如何沟通(不只是纯粹的RPC)。 它具有请求/回复,推/拉,pub / sub和pair的模式。 它为您提供了足够的工具来组合可扩展的任何types的系统。

我已经使用了,他们是很好的解决scheme。

就像一个非常粗略的例子,Thrift规范可能是这样的。 比方说,你想要从python事件传递到node.js,让它处理,并得到一些回应:

myspec.thrift

 struct Event { 1: string message; } service RpcService { string eventOccurred(1:Event e) } 

这定义了一个名为Event的数据结构,其中包含一个string成员来保存消息。 然后,一个名为RpcService的服务定义了一个名为eventOccured的函数,它将一个Event作为参数,并返回一个string。

当您为python和node.js生成此代码时,可以使用用于python的客户端代码和用于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); 

你可以看看一些消息系统,如0mq http://www.zeromq.org/

我用这个问题的灵感来将diagnosis.py转换成一个Socket.IO客户端。 这样我可以将实时数据发送到Node.js Socket.IO服务器:

 socketIO.emit('gaze', ...) 

然后让它做一个socket.broadcast.emit发送数据到所有的Socket.IO客户端(browser和diagnostics.py)。

RPC可能是更为标准的跨语言开发方法,但是我认为在交换数据的目标时这样做有点矫枉过正。 它也不支持开箱即用的IO。

更新于2013年1月由于socket.broadcast.emit产生大量不必要的stream量,我试图find一个更好的方式来做到这一点。 我想到的解决scheme是使用我提到的基本的python Socket.IO客户端库支持的命名空间。

python

 self.mainSocket = SocketIO('localhost', 80) self.gazeSocket = self.mainSocket.connect('/gaze') self.gazeSocket.emit('gaze', ...) 

连接到注视名称空间。

Node.js的

 var gaze = io.of('/gaze').on('connection', function (socket) { socket.on('gaze', function (gdata) { gaze.emit('gaze', gdata.toString()); }); }); 

这只会将接收到的数据发送给连接到注视名称空间的客户端。

浏览器

 var socket = io.connect('http://localhost/gaze'); socket.on('gaze', function (data) { console.log(data); }); 

如果你只是想找一些在套接字之上给你一个简单协议的东西,那么你不必处理缓冲和分隔消息以及所有这些东西,这两个明显的select(取决于你的数据types,重新尝试发送)是netstrings和JSON-RPC。 两种语言都有多种库的select,但是最终代码可以像这样简单:

 class MyService(Service): # … code to set up the newsdb def getnews(self, category, item): return self.newsdb.get(category, item) myService = MyService(6000) myService = Service(6000) // … code to set up the newsdb myService.getnews = function(category, item, callback) { callback(this.newsdb.get(category, item); }