Skip to main content

3 posts tagged with "python"

View All Tags

· 5 min read

女朋友正在学习python,写的脚本都是从stdin输入,从stdout输出的;而我又是一个js全栈,感觉写一个简单的python脚本调用的界面+nodejs微服务应该很有意思。

#demo http://ali.wusisu.com/sun/

child_process

首先我要先实现在nodejs中调用python,并且要转发输入输出流。

'use strict'
var child_process = require('child_process')
var cp = child_process.spawn('python3', ['./files/circumference.py'])
cp.stdout.pipe(process.stdout)
process.stdin.pipe(cp.stdin)
cp.on('close', (code) => {
process.exit(code)
})

做的事情简单清晰易懂:

  1. 用child_process的spawn调用一个python3进程cp。
  2. 转发cp的标准输出到当前程序的标准输出(命令行)。
  3. 转发当前程序的标准输入到cp的标准输入。
  4. 监听cp的结束事件。

结果是调用这个node wrapper.js跟直接调用python3 ./files/circumference.py没有任何区别。

曲折

事实上开发的时候走了点弯路的。 我很幼稚的认为,使用Content-Type: text/event-stream能够解决问题。 只要client端发起一个POST请求,但不马上结束连接,而是持续的发送内容;server端使用event-stream持续地返回内容。 事实上我已经把模拟的client端和server端写好了,也完全达到了目标效果,然并卵,在js里没法用ajax慢慢地发POST请求。

event-stream: 告诉client/browser服务器会慢慢地返回内容,你收到多少直接拿去用就好。

socket.io

socket.io也并没有什么需要说的了,就简单推荐一下,好用。

websocket

在socket.io之前我考虑过直接上websocket,因为之前用event-stream实现的时候并没有使用第三方的包,直接用原生的http然后把streampipe出去可爽了。于是就想着原生上websocket。 nodejs的文档其实提到了一下websocket的。文中让我响应upgrade事件然后可以拿到一个socket然后可以pipe给它自己。 然后就没有更多关于怎么发起一个websocket的资讯了。然而在google/baidu等搜索引擎中,并未能找到关于websocket足够给我用的实践,全都在不清不楚地大概说websocket有什么好处,像什么样子。(如果以后有空,自己实践一下,再上文章) 反倒是有了新的东西,在要求upgrade的时候要带一个base64的key,然后在服务器response的时候要给另外一个encrypted的base64。然后还不说这个key是干什么的,简直就是各种不清不楚。

文件遍历/Promise

之前习惯用stage-2async来写同步执行。不过现在babel还没有全面进入node-v5.7.1,要用async需要引入许多babel包和配置,正好前面都做比较原生的事情,于是想着用原生来写。 首先考虑了callback写法,遍历./files目录后调用回调。结果发现Promise.all还是做了不少事情,把这个写到我的递归函数中还是比较难看的,于是还是上Promise吧。

var fs = require('fs')
var lookForwardFiles = function(path){
return new Promise((res,rej)=>{
fs.stat(path, (err, stat)=>{
if(err) return res([])
if(!stat.isDirectory()) return res([path])
fs.readdir(path, (err, files)=>{
if(err) return res([])
var allP = files.map(f=>lookForwardFiles(path + '/' + f))
Promise.all(allP).then(data=>res([].concat.apply([],data)))
})
})
})
}

node支持了arrow functions还是蛮爽的,就是用=>来代替'function'。 这里用到了一个技巧[].concat.apply([],data),可以把形如[[1,2],[3],[4],5]的data转化为[1,2,3,4,5]。 其实也可以用

data.reduce((all,d)=>all.concat(d),[])

来代替。

commit

给个当前commit的链接,万一以后不用socket.io上原生websocket了呢。

· One min read

有做一个远程开机的需要,所以python代码如下

-*- coding: utf-8 -*-
import socket
import struct

s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_BROADCAST,1)

data = ""
for i in range(6):
data += struct.pack('B',255)

mac = "DC-9C-52-11-3E-A8"
macs = map(lambda x:int(x,16),mac.split('-'))
for i in range(16):
data += struct.pack('6B',*macs)

print repr(data)

s.sendto(data,('255.255.255.255',7))
s.close()

其中那个端口为7或者9,有些说的是随便什么端口都行。实测88是可以的。

· 4 min read

我的任务是把python的一个项目移植到linux下。pyactivemq在windows下只用直接下载一个pyd就好,而linux要编译。而这个项目已经好几年没有人动过了,所以有很多依赖的项目需要选择特定版本而不是最新版本。

首先解释几个名词:

  • JMS(java message service):java信使服务。一般称为jms中间件。
  • activemq:大概是active message queue的意思吧。我不太了解activemq和jms之间的关系,但是把他俩等价视之在大部分情况下都是对的。
  • openwire & stomp:activemq支持的两种协议,区别好像是stomp只支持文本信息,而openwire支持文本和字节流两种。估计也是因为如此,openwire只支持C、C++以及C#;而stomp在各类主流语言中都有现成的客户端。
  • pyactivemq:这是python下支持openwire的module,这不跟上面我说的矛盾,因为他就是由C++版本的activemq编译成的。

好了,因为公司的架构是基于openwire的,而重新开一个stomp协议给我动静比较大(我一个人搞不定),所以先试着编译个linux下的pyactivemq。

这个教程很重要,在pyactivemq的项目中有链接过去。

  1. 首先去上面的4点过去看看,上面写得很清楚了,需要activemq-cpp,而且要2.2.6的版本的。好了,下载好准备编译。另外需要几个包: sudo apt-get install libboost-python-dev libcppunit-dev uuid-dev autoconf automake libtool build-essential
  2. 看看readme,也说得很清楚,需要别的几个项目,能够apt掉的自然直接apt,但是apr(apache portable runtime)需要自己编译,因为我发现通过apt-get来的apr版本太高,会configure不过。
  3. 好,去下载apr和apr-util。嗯,实测apr-1.3.12和apr-util-1.3.12能编译运行,是我千辛万苦找来的下载地址。
  4. 好,编译安装要教吗?先装apr:进入文件夹,./configure --prefix=/opt/apr/,make,sudo make install。再装apr-util:进入文件夹,./configure --prefix=/opt/apr-util/ --with-apr=/opt/apr/,make,sudo make install。这里在configure的时候指定了安装地址,因为后面的安装需要找到之前的项目地址,而我又不想把他装到系统中,因为老版本的apr会影响别的项目的,比如我的apache2服务器在把这些东西安装到系统环境中就运行不了了。
  5. 然后就是activemq-cpp了。进入文件夹,mkdir config,./autogen.sh,./configure --prefix=/opt/activemq-cpp --with-apr=/opt/apr/ --with-apr-util=/opt/apr-util/,make,sudo make install。这里呢要先用autogen.sh来生成configure,然后再继续。
  6. 最后是编译pyactivemq了。在pyactivemq的源码文件夹,可以看到说明文档,两步,python setup.py build以及sudo python setup.py install。但是在这之前,你要先修改setup.py,把里面3处地址改正确。 好了,大功告成。