今天想要写个python脚本来把我们之前一个项目中使用的gpb格式导出的数据打印出来,由于之前接触python很少,所以基本是从头学起
基本的语法的话我就不说了,我主要记录一下我的几个环境配置
python和ide:
安装了python2.6, editplus. 网上有一篇介绍怎么在editplus中编辑/编译/运行python脚本的文章,照搬就ok了.
gpb:
gpb我算是比较熟悉了,但是之前也只在c++和java中用到,没在python中使用,compiler的用法基本是一样的,指定—python_out的路径就行了,生成的文件打开一看,和java,C++的有很大的区别,具体的可以自己去生成一个试一下,gpb的官方文档中也有详细讲解,我就不多说,我主要说一下这个生成的文件要在python中用起来,还需要把gpb的lib装到python的lib目录下面去,我直接把gpb2.3.0源码目录下python目录中的google目录整个粘贴过去,但是不行,没有效果,import仍然会出错.
然后看了一下README,才知道要运行setup.py,试了一下,还需要在cygwin下面运行,然后就会安装到python的lib目录下面去,再使用就ok了.
python中的用法:
这个实际官方也有文档说明,因为我这里主要是反序列化,所以用ParseFromString方法就行了.我主要想提一点,由于我们序列化输出之后,大多是在网络流或者文件中,那么怎么来获取到我们的pb对应的byte数组呢.略微查了一下python的手册,看到有struct这个类可以使用.比如我们写在文件中格式是 [整型长度][pb字节数组],那么我们读取到的字节数组就可以用struct.unpack_from(“ip”, data)来进行解析,前面的 i 就表示整型长度,后面的 p 就是一个char数组.目前呢,因为写在文件中的数据是上述格式的多个循环,故可采用unpack_from后面多加一个offset参数,进行下一次的解析,不过这部分我还没尝试,至少前面的经过尝试是可以使用的.
后记:
后来我尝试用unpack_from来解决循环取数据的问题,发现不可行,整了半天最后仔细一想,觉得自己把简单的问题复杂话了.
应该从python的设计角度去考虑一下这个问题,python里面没有byte数组,看看file.read方法就知道,它读取出来的byte数组在python中实际是list对象,而list来说就有很方便的获取其中某一段作为一个新的list,换个说法就是把byte数组中的一段取出作为一个新的byte数组,这不就正是我需要的么.所以,我只需要每次用unpack_from获取到一个整型的长度,然后计算出正确的偏移量,就可以取出pb数据.再计算出新的偏移量去取下一条数据的长度,如此循环.
2012.6.7 后记:
上次研究之后,在2.3的基础上做了一些修改,让它支持打印中文,后来一直没记录,再后来硬盘坏了之后,一切化为乌有。
今天又想要做一个工具打印一些服务器下载的pb数据,又碰到中文打印问题,记得当时研究2.3的时候看了2.4的代码,是支持中文的,今天就直接用2.4了,结果打印出来还是不是中文。折腾了一会才解决问题,print pb.__unicode__().encode("gb2312")