python nodejs混合_昆仑的山头 » 让python和nodejs一起玩耍

做树莓派,为什么还要用nodejs?

没啥特别原因,主要是自己对nodejs+webscoket这套玩的比较熟,而对python的web开发没啥研究

所以,定下这样一个技术方案:python负责硬件驱动和底层逻辑,nodejs负责上面的“好玩”的东西,也就是一般说的“业务逻辑”,web/webscoket服务服务由nodejs提供~

那么问题来了,如何让python和nodejs可以方便的互相调用哪?

按照自己的知识储备,大概有三个方案,按照优先级:

1. 双向的webscoket

2. 单向的thrift,python和nodejs各建一个server端和一个client端,实现双向通信

3. 单向的http,和上面的思路类似,但是速度会比thrift慢一个数量级

webscoket最好用,可以和页面通讯实现极速统一,而且一个连接就可以实现双向通讯,~~但是协议相对复杂,本来想使用nodejs的socket.io,让nodejs做server,python做client,但是试了几种方案都连不上,如果手动实现webscoket通讯协议。。。算了吧,还是下一个吧

第2个方案其实也不顺利,由于对python不熟悉,thrift的库文件导了几次总是失败,拖了几天仔细研究了python的import方式才算成功

这样,整个系统的方案也就是这样

(我的初步打算是做一个能自主行走、壁障,又能用手机网页遥控的机器人,所以硬件部分是直流电机控制芯片、超声测距、红外感应)

下面就来分享一下nodejs与python基于thrift做互联的代码,根据这个方案,对于不熟悉python又想在树莓派上实现较复杂业务逻辑的人,完全可以将nodejs换成自己更熟悉的语言,对于thrift不熟悉的朋友,可以自己学习:http://thrift.apache.org

和一般的thrift的思路不同,为了简化代码逻辑,这里其实类似http接口,action类似url,post一坨键值对,然会返回一坨信息,之所以这么设计,是因为一直觉得thrift太啰嗦,每次添加新接口还要替换定义文件

thrift定义文件:

/**

* 统一的返回值

*/

struct Retu{

1: i32 code, //返回码

2: string msg, //返回错误时的详细信息

3: map data//map/字典 类型的返回值

}

/**

* 异常信息

*/

exception UException{

1:i32 errorCode, //错误码 1=参数错误,2=没有结果 99=系统异常

2:string errorMessage //错误描述

}

service PiMessService{

Retu c(1:string action, 2:map params) throws (1:UException ex),

}

python端:

#coding:utf-8

import sys, glob, os

import event #这里是自己封装的python事件中心,可以订阅、触发事件,以后有机会单独给大家分享

rootPath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

sys.path.append(rootPath + '/lib/gen-py') #thrift库文件位置

from thrift.transport import TSocket

from thrift.transport import TTransport

from thrift.protocol import TBinaryProtocol

from thrift.server import TServer

import piMess.PiMessService as PiMessService

import piMess.ttypes as ttypes

#####server start#####

class PiMessHandler:

def __init__(self):

self.log = {}

#会被client调用的方法

def c(self, action, params):

#收到一次调用,其实是触发一次特定事件,程序其他部分可以去订阅这个事件,返回给出返回值

rets = event.trigger('tele_' + action, params)

msg = ''

data = {}

if(len(rets) > 0): #以第一个绑定的返回值为准,后续可以根据实际需求在扩展

if(type(rets[0]) == type('')):#只使用字符串和字典值

msg = rets[0]

elif(type(rets[0]) == type({})):

data = rets[0]

return ttypes.Retu(200, msg, data)

#启动服务

def serviceStart():

print 'PiMessService start on 9001 ...'

handler = PiMessHandler()

processor = PiMessService.Processor(handler)

transport = TSocket.TServerSocket(port=9001) #python server端的端口

tfactory = TTransport.TBufferedTransportFactory()

pfactory = TBinaryProtocol.TBinaryProtocolFactory()

server = TServer.TSimpleServer(processor, transport, tfactory, pfactory)

server.serve()

print 'done~'

#####server end#######

#####client start#####

__transport = TSocket.TSocket('localhost', 9002) #nodejs server端的端口

__transport = TTransport.TBufferedTransport(__transport)

__protocol = TBinaryProtocol.TBinaryProtocol(__transport)

__client = PiMessService.Client(__protocol)

def clientOpen():

__transport.open()

#供外部调用的向nodejs端发送消息的方法

def send(action, params):

r = __client.c(action, params)

print('call nodejs:', action, params, r)

return r

def clientClose():

__transport.close()

#####client end#######

if __name__ == "__main__":

clientOpen()

send('py-client', {'QQQ': 'ZZZ', 'abc':'PPP'})

serviceStart()

nodejs端:

var thrift = require('thrift');

var Thrift = thrift.Thrift;

var piMessService = require('../gen-nodejs/PiMessService'),

ttypes = require('../gen-nodejs/piMess_types');

/***server start***/

var server = thrift.createServer(piMessService, {

c: function(action, params, result){

//server,可以根据action值,调用对应的外部方法

console.log('piMessService.c:', action, params);

retu = new ttypes.Retu({code:200, msg:'ok', data:null});

result(null, retu);

}

}, {});

server.listen(9002);

/***server end*****/

/***client start***/

var connection = thrift.createConnection('localhost', 9001),

client = thrift.createClient(piMessService, connection);

//对外暴漏一个send方法

exports.send = function(action, params, callback){

console.log('exports.send:', action, params);

client.c(action, params, function(err, response){

if(response){

console.log('response:', response);

}

callback && callback(err, response);

});

};

exports.clientEnd = function(){

connection.end();

};

/***client end*****/

over

———

转载请注明出处:昆仑的山头

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值