Pickle 跨平台 __dict__ 属性错误
我在使用pickle的时候遇到了一些问题。在OSX和Linux之间一切正常,但在Windows和Linux之间就不行了。所有的pickle字符串都存储在内存中,并通过SSL套接字发送。为了更清楚,我把所有的'\n'替换成了":::",把所有的'\r'替换成了"==="(其实没有'\r')。场景如下:
- 客户端-Win:运行Python 2.7的小型企业服务器2011
- 客户端-Lin:运行Python 2.7的Fedora Linux
- 服务器:运行Python 2.7的Fedora Linux
客户端-Lin向服务器发送一个pickle对象:
ccopy_reg:::_reconstructor:::p0:::(c__main__:::infoCollection:::p1:::c__builtin__:::tuple:::p2:::(VSTRINGA:::p3:::VSTRINGB:::p4:::VSTRINGC:::p5:::tp6:::tp7:::Rp8:::.
客户端-Win向服务器发送一个pickle对象:
ccopy_reg:::_reconstructor:::p0:::(c__main__:::infoCollection:::p1:::c__builtin__:::tuple:::p2:::(VSTRINGA:::p3:::VSTRINGB:::p4:::VSTRINGC:::p5:::tp6:::tp7:::Rp8:::ccollections:::OrderedDict:::p9:::((lp10:::(lp11:::S'string_a':::p12:::ag3:::aa(lp13:::S'string_b':::p14:::ag4:::aa(lp15:::S'string_c':::p16:::ag5:::aatp17:::Rp18:::b.
奇怪的是,Windows客户端发送的pickle里多了些信息,而当Linux客户端尝试加载这个pickle字符串时,我收到了:
Unhandled exception in thread started by <function TestThread at 0x107de60>
Traceback (most recent call last):
File "./test.py", line 212, in TestThread
info = pickle.loads(p_string)
File "/usr/lib64/python2.7/pickle.py", line 1382, in loads
return Unpickler(file).load()
File "/usr/lib64/python2.7/pickle.py", line 858, in load
dispatch[key](self)
File "/usr/lib64/python2.7/pickle.py", line 1224, in load_build
d = inst.__dict__
AttributeError: 'infoCollection' object has no attribute '__dict__'
有什么想法吗?
编辑
添加了一些额外的信息请求。
infoCollection类的定义是一样的:
infoCollection = collections.namedtuple('infoCollection', 'string_a, string_b, string_c')
def runtest():
info = infoCollection('STRINGA', 'STRINGB', 'STRINGC')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
ssl_sock.connect((server, serverport))
ssl_sock.write(pickle.dumps(info))
ssl_sock.close()
接收函数也差不多,但做了一个
p_string = ssl_sock.read()
info = pickle.loads(p_string)
5 个回答
如果你这样做,会发生什么呢?
p_string = ssl_sock.read(nbytes=1.0E6)
info = pickle.loads(p_string)
你是不是在用不同的小版本的Python?在2.7.3这个版本里,有个bug导致用来保存和读取命名元组的功能和旧版本不兼容。你可以看看这个链接了解更多:
http://ronrothman.com/public/leftbraned/python-2-7-3-bug-broke-my-namedtuple-unpickling/
这是个小技巧,但在不同平台上出现的问题似乎是因为使用了命名元组(namedtuples)和序列化工具(pickle)一起在跨平台环境中造成的。我把命名元组换成了我自己定义的类,结果一切都正常了。
class infoClass(object):
pass
def infoCollection(string_a, string_b, string_c):
i = infoClass()
i.string_a = string_a
i.string_b = string_b
i.string_c = string_c
return i