cPickle序列化自定义类实例时的陷阱
在用C/C++写网络打包/解包时,都是自己用指针偏移来实现对象<->二进制之间的互转,现在既然用了python,也要用一下序列化的思想,所以就使用cPickle来完成这件事情。
不过事情并不顺利……
假设我们在server端和client端通过类MManRsp来进行通信,这个类定义在mmanpro.py中,代码如下:
class MManRsp:
ret = 0
pathverlist = []
现在server端对client端回包如下:(源代码并非如此,为了演示,所以简化了代码)
rsp = MManRsp()
data = [('1',1),('2',2)]
for t in data:
x = do_something(t)#还是返回('1',1)这种类型
rsp.pathverlist.append(x)
senddata = cPickle.dumps(rsp)
#send
client端解析为:
rsp = cPickle.loads(recvdata)
print rsp.pathverlist
在运行这段代码的时候,client的print结果会是 []。
在经过漫长的原因查找之后终于知道,原来cPickle在序列化类实例时,对类内部变量是用引用的方式储存的,那么杯具的事情就来了,在server端,cPickle把引用序列化到了流中,而在client端根本就不不认识这个引用……(我浅显的理解,不对请大家千万指明)
所以需要在server端做如下修改:
rsp = MManRsp()
data = [('1',1),('2',2)]
newdata = []
for t in data:
x = do_something(t)#还是返回('1',1)这种类型
newdata.append(x)
rsp.pathverlist = copy.deepcopy(newdata)
senddata = cPickle.dumps(rsp)
这样就正常了。
但是还是剩下两点比较困惑:
1.rsp.pathverlist = copy.deepcopy(newdata),如果改成 rsp.pathverlist = newdata 也可以解决问题,不是说所有的赋值都引用么,奇怪……
2.在client端loads的时候,cPickle会自动找寻mmanpro.MManRsp这个模块,都不用在client的代码中加入from mmanpro import MManRsp
对python的了解还是不深,希望有知道原因的朋友能够不吝赐教。
另:
在网上看到一个关于cPickle的文档,写的很好。
http://www.ibm.com/developerworks/cn/linux/l-pypers/
建议继续学习:
- JavaScript性能陷阱 (阅读:3161)
- Java陷阱(2010版) (阅读:3313)
- PHP数据类型隐性转换的陷阱 (阅读:3011)
- 移动互联网系统架构十大陷阱 (阅读:2896)
- 类型转换-无处不在的陷阱 (阅读:2318)
- JavaScript 中的陷阱 (阅读:1892)
- 可能被你忽略的 JavaScript 代码陷阱 (阅读:1732)
- 情景反射陷阱 (阅读:1721)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:Dante 来源: Vimer
- 标签: cPickle 陷阱
- 发布时间:2010-05-19 13:52:09
- [69] Twitter/微博客的学习摘要
- [67] IOS安全–浅谈关于IOS加固的几种方法
- [65] 如何拿下简短的域名
- [65] android 开发入门
- [63] find命令的一点注意事项
- [62] Go Reflect 性能
- [61] 流程管理与用户研究
- [60] Oracle MTS模式下 进程地址与会话信
- [59] 图书馆的世界纪录
- [57] 读书笔记-壹百度:百度十年千倍的29条法则