IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

cPickle序列化自定义类实例时的陷阱

Vimer 2010-05-19 13:52:09 累计浏览 2,675 次
本机暂存

在用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/

同分类推荐文章

  1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. 用Hyer来进行网站的抓取 (累计阅读 158,251)
  2. 配置Nginx+uwsgi更方便地部署python应用 (累计阅读 107,165)
  3. 程序员技术练级攻略 (累计阅读 35,471)
  4. python实现自动登录discuz论坛 (累计阅读 32,834)
  5. python编程细节──遍历dict的两种方法比较 (累计阅读 20,371)
  6. 每个程序员都应该学习使用Python或Ruby (累计阅读 17,918)
  7. Chrome和goagent的配置方法,你懂的 (累计阅读 16,843)
  8. 30分钟3300%性能提升――python+memcached网页优化小记 (累计阅读 13,742)
  9. 使用python爬虫抓站的一些技巧总结:进阶篇 (累计阅读 13,302)
  10. 我的PHP,Python和Ruby之路 (累计阅读 13,147)