I’m having an issue with pickle. Things work fine between OSX and Linux, but not Windows and Linux. All pickled strings are stored in memory and sent via an SSL socket. To be 100% clear I have replaced all ‘\n’s with “:::” and all ‘\r’s with “===” (there were none). Scenario:
- Client-Win: Small Business Server 2011 running Python 2.7
- Client-Lin: Fedora Linux running Python 2.7
- Server: Fedora Linux running Python 2.7
Client-Lin sends a pickled object to Server:
ccopy_reg:::_reconstructor:::p0:::(c__main__:::infoCollection:::p1:::c__builtin__:::tuple:::p2:::(VSTRINGA:::p3:::VSTRINGB:::p4:::VSTRINGC:::p5:::tp6:::tp7:::Rp8:::.
Client-Win sends a picked object to Server:
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.
For some reason the Windows client sends extra information along with the pickle, and when the Linux client tries to load the pickle string I get:
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__'
Any ideas?
EDIT
Adding additional requested information.
The infoCollection class is defined the same way:
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()
And the receiving function is much the same but does a
p_string = ssl_sock.read()
info = pickle.loads(p_string)
A hack, but the cross-platform issue appears to be due to namedtuples and pickle together in a cross-platform environment. I have replaced the namedtuple with my own class and all works well.