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

mel*_*iny 17 html python node.js socket.io

你有一个python脚本diagnosis.py,可以生成基于事件的实时数据.使用Node.js,您可以将其作为子进程启动并捕获其输出,然后使用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());
    });
});
Run Code Online (Sandbox Code Playgroud)

客户

<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>
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

更新我回答了我自己的问题,但我对另一种方法持开放态度.虽然RPC不是我想要的.

jdi*_*jdi 7

Apache Thrift是一种在所有主要语言之间编写RPC代码的非常棒的方法.您编写了一个声明类型和服务的通用Thrift规范,然后代码生成器为您所需的语言创建绑定.你可以在你的节点和python代码库之间调用方法.

在更通用的低级方法中,ZeroMQ是一个消息队列库,它也支持所有主要语言.有了这个,您可以设计自己的解决方案,以便进行通信(而不仅仅是纯粹的RPC).它具有请求/回复,推/拉,发布/订阅和配对的模式.它为您提供了足够的工具来组合任何类型的可扩展系统.

我使用过它们,它们都是很好的解决方案.

就像一个非常粗略的例子,Thrift规范可能是这样的.假设您想要将事件从python传递到node.js,处理它并获得一些响应:

myspec.thrift

struct Event {
    1: string message; 
}

service RpcService {
    string eventOccurred(1:Event e)
}
Run Code Online (Sandbox Code Playgroud)

这定义了一个Event用单个字符串成员调用的数据结构来保存消息.然后一个名为RpcServicedefine的函数定义了一个函数eventOccured,该函数需要Event一个参数作为参数,并返回一个字符串.

当您为python和node.js生成此代码时,您可以使用python的客户端代码和node.js的服务器端代码

蟒蛇

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
Run Code Online (Sandbox Code Playgroud)

的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);
Run Code Online (Sandbox Code Playgroud)


mel*_*iny 2

我使用受此问题启发的库将其变成diagnosis.py了 Socket.IO 客户端。这样我就可以将实时数据发送到 Node.js Socket.IO 服务器:

socketIO.emit('gaze', ...)
Run Code Online (Sandbox Code Playgroud)

然后让它将socket.broadcast.emit数据发送到所有 Socket.IO 客户端(浏览器和diagnosis.py)。

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

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

Python

self.mainSocket = SocketIO('localhost', 80)
self.gazeSocket = self.mainSocket.connect('/gaze')
self.gazeSocket.emit('gaze', ...)
Run Code Online (Sandbox Code Playgroud)

连接到凝视名称空间。

Node.js

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

这仅将接收到的数据发送给连接到 Gaze 命名空间的客户端。

浏览器

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