blob: a481fc7fce9262bb1ccd911db0dd3c11ff90940a [file] [log] [blame]
Guido van Rossuma48061a1995-01-10 00:31:14 +00001"""\
2Pickling Algorithm
3------------------
4
5This module implements a basic but powerful algorithm for "pickling" (a.k.a.
6serializing, marshalling or flattening) nearly arbitrary Python objects.
7This is a more primitive notion than persistency -- although pickle
8reads and writes file objects, it does not handle the issue of naming
9persistent objects, nor the (even more complicated) area of concurrent
10access to persistent objects. The pickle module can transform a complex
11object into a byte stream and it can transform the byte stream into
12an object with the same internal structure. The most obvious thing to
13do with these byte streams is to write them onto a file, but it is also
14conceivable to send them across a network or store them in a database.
15
16Unlike the built-in marshal module, pickle handles the following correctly:
17
18- recursive objects
19- pointer sharing
Guido van Rossum0c891ce1995-03-14 15:09:05 +000020- classes and class instances
Guido van Rossuma48061a1995-01-10 00:31:14 +000021
22Pickle is Python-specific. This has the advantage that there are no
23restrictions imposed by external standards such as CORBA (which probably
24can't represent pointer sharing or recursive objects); however it means
25that non-Python programs may not be able to reconstruct pickled Python
26objects.
27
28Pickle uses a printable ASCII representation. This is slightly more
29voluminous than a binary representation. However, small integers actually
30take *less* space when represented as minimal-size decimal strings than
31when represented as 32-bit binary numbers, and strings are only much longer
32if they contain control characters or 8-bit characters. The big advantage
33of using printable ASCII (and of some other characteristics of pickle's
34representation) is that for debugging or recovery purposes it is possible
35for a human to read the pickled file with a standard text editor. (I could
36have gone a step further and used a notation like S-expressions, but the
37parser would have been considerably more complicated and slower, and the
38files would probably have become much larger.)
39
40Pickle doesn't handle code objects, which marshal does.
41I suppose pickle could, and maybe it should, but there's probably no
42great need for it right now (as long as marshal continues to be used
43for reading and writing code objects), and at least this avoids
44the possibility of smuggling Trojan horses into a program.
45
46For the benefit of persistency modules written using pickle, it supports
47the notion of a reference to an object outside the pickled data stream.
48Such objects are referenced by a name, which is an arbitrary string of
49printable ASCII characters. The resolution of such names is not defined
50by the pickle module -- the persistent object module will have to implement
51a method "persistent_load". To write references to persistent objects,
52the persistent module must define a method "persistent_id" which returns
53either None or the persistent ID of the object.
54
55There are some restrictions on the pickling of class instances.
56
57First of all, the class must be defined at the top level in a module.
58
Guido van Rossum37a6f161996-08-08 18:35:22 +000059Next, it must normally be possible to create class instances by
60calling the class without arguments. Usually, this is best
61accomplished by providing default values for all arguments to its
62__init__ method (if it has one). If this is undesirable, the
63class can define a method __getinitargs__, which should return a
64*tuple* containing the arguments to be passed to the class
Guido van Rossuma48061a1995-01-10 00:31:14 +000065constructor.
66
Guido van Rossum0c891ce1995-03-14 15:09:05 +000067Classes can influence how their instances are pickled -- if the class defines
Guido van Rossuma48061a1995-01-10 00:31:14 +000068the method __getstate__, it is called and the return state is pickled
69as the contents for the instance, and if the class defines the
70method __setstate__, it is called with the unpickled state. (Note
71that these methods can also be used to implement copying class instances.)
72If there is no __getstate__ method, the instance's __dict__
73is pickled. If there is no __setstate__ method, the pickled object
74must be a dictionary and its items are assigned to the new instance's
75dictionary. (If a class defines both __getstate__ and __setstate__,
76the state object needn't be a dictionary -- these methods can do what they
77want.)
78
79Note that when class instances are pickled, their class's code and data
80is not pickled along with them. Only the instance data is pickled.
81This is done on purpose, so you can fix bugs in a class or add methods and
82still load objects that were created with an earlier version of the
83class. If you plan to have long-lived objects that will see many versions
84of a class, it may be worth to put a version number in the objects so
85that suitable conversions can be made by the class's __setstate__ method.
86
87The interface is as follows:
88
Guido van Rossum256cbd71995-02-16 16:30:50 +000089To pickle an object x onto a file f, open for writing:
Guido van Rossuma48061a1995-01-10 00:31:14 +000090
91 p = pickle.Pickler(f)
92 p.dump(x)
93
94To unpickle an object x from a file f, open for reading:
95
96 u = pickle.Unpickler(f)
Guido van Rossum48aa82e1995-04-10 11:34:46 +000097 x = u.load()
Guido van Rossuma48061a1995-01-10 00:31:14 +000098
99The Pickler class only calls the method f.write with a string argument
100(XXX possibly the interface should pass f.write instead of f).
101The Unpickler calls the methods f.read(with an integer argument)
102and f.readline(without argument), both returning a string.
103It is explicitly allowed to pass non-file objects here, as long as they
104have the right methods.
105
106The following types can be pickled:
107
108- None
109- integers, long integers, floating point numbers
110- strings
Guido van Rossum256cbd71995-02-16 16:30:50 +0000111- tuples, lists and dictionaries containing only picklable objects
Guido van Rossuma48061a1995-01-10 00:31:14 +0000112- class instances whose __dict__ or __setstate__() is picklable
Guido van Rossum0c891ce1995-03-14 15:09:05 +0000113- classes
Guido van Rossuma48061a1995-01-10 00:31:14 +0000114
115Attempts to pickle unpicklable objects will raise an exception
116after having written an unspecified number of bytes to the file argument.
117
118It is possible to make multiple calls to Pickler.dump() or to
119Unpickler.load(), as long as there is a one-to-one correspondence
Guido van Rossum256cbd71995-02-16 16:30:50 +0000120between pickler and Unpickler objects and between dump and load calls
Guido van Rossuma48061a1995-01-10 00:31:14 +0000121for any pair of corresponding Pickler and Unpicklers. WARNING: this
122is intended for pickleing multiple objects without intervening modifications
123to the objects or their parts. If you modify an object and then pickle
124it again using the same Pickler instance, the object is not pickled
125again -- a reference to it is pickled and the Unpickler will return
126the old value, not the modified one. (XXX There are two problems here:
127(a) detecting changes, and (b) marshalling a minimal set of changes.
128I have no answers. Garbage Collection may also become a problem here.)
129"""
130
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000131__version__ = "1.6" # Code version
Guido van Rossuma48061a1995-01-10 00:31:14 +0000132
133from types import *
134import string
135
Guido van Rossum0c891ce1995-03-14 15:09:05 +0000136format_version = "1.1" # File format version we write
137compatible_formats = ["1.0"] # Old format versions we can read
138
Guido van Rossum7849da81995-03-09 14:08:35 +0000139PicklingError = "pickle.PicklingError"
140
Guido van Rossuma48061a1995-01-10 00:31:14 +0000141AtomicTypes = [NoneType, IntType, FloatType, StringType]
142
143def safe(object):
144 t = type(object)
145 if t in AtomicTypes:
146 return 1
147 if t is TupleType:
148 for item in object:
149 if not safe(item): return 0
150 return 1
151 return 0
152
153MARK = '('
154POP = '0'
155DUP = '2'
156STOP = '.'
157TUPLE = 't'
158LIST = 'l'
159DICT = 'd'
160INST = 'i'
Guido van Rossum0c891ce1995-03-14 15:09:05 +0000161CLASS = 'c'
Guido van Rossuma48061a1995-01-10 00:31:14 +0000162GET = 'g'
163PUT = 'p'
164APPEND = 'a'
165SETITEM = 's'
166BUILD = 'b'
167NONE = 'N'
168INT = 'I'
169LONG = 'L'
170FLOAT = 'F'
171STRING = 'S'
172PERSID = 'P'
173AtomicKeys = [NONE, INT, LONG, FLOAT, STRING]
174AtomicMap = {
175 NoneType: NONE,
176 IntType: INT,
177 LongType: LONG,
178 FloatType: FLOAT,
179 StringType: STRING,
180}
181
182class Pickler:
183
184 def __init__(self, file):
185 self.write = file.write
186 self.memo = {}
187
188 def dump(self, object):
189 self.save(object)
190 self.write(STOP)
191
192 def save(self, object):
193 pid = self.persistent_id(object)
194 if pid:
195 self.write(PERSID + str(pid) + '\n')
196 return
197 d = id(object)
198 if self.memo.has_key(d):
199 self.write(GET + `d` + '\n')
200 return
201 t = type(object)
Guido van Rossum7849da81995-03-09 14:08:35 +0000202 try:
203 f = self.dispatch[t]
204 except KeyError:
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000205 if hasattr(object, '__class__'):
206 f = self.dispatch[InstanceType]
207 else:
208 raise PicklingError, \
209 "can't pickle %s objects" % `t.__name__`
Guido van Rossum7849da81995-03-09 14:08:35 +0000210 f(self, object)
Guido van Rossuma48061a1995-01-10 00:31:14 +0000211
212 def persistent_id(self, object):
213 return None
214
215 dispatch = {}
216
217 def save_none(self, object):
218 self.write(NONE)
219 dispatch[NoneType] = save_none
220
221 def save_int(self, object):
222 self.write(INT + `object` + '\n')
223 dispatch[IntType] = save_int
224
225 def save_long(self, object):
226 self.write(LONG + `object` + '\n')
227 dispatch[LongType] = save_long
228
229 def save_float(self, object):
230 self.write(FLOAT + `object` + '\n')
231 dispatch[FloatType] = save_float
232
233 def save_string(self, object):
234 d = id(object)
235 self.write(STRING + `object` + '\n')
236 self.write(PUT + `d` + '\n')
237 self.memo[d] = object
238 dispatch[StringType] = save_string
239
240 def save_tuple(self, object):
241 d = id(object)
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000242 write = self.write
243 save = self.save
244 has_key = self.memo.has_key
245 write(MARK)
Guido van Rossuma48061a1995-01-10 00:31:14 +0000246 n = len(object)
247 for k in range(n):
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000248 save(object[k])
249 if has_key(d):
Guido van Rossuma48061a1995-01-10 00:31:14 +0000250 # Saving object[k] has saved us!
251 while k >= 0:
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000252 write(POP)
Guido van Rossuma48061a1995-01-10 00:31:14 +0000253 k = k-1
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000254 write(GET + `d` + '\n')
Guido van Rossuma48061a1995-01-10 00:31:14 +0000255 break
256 else:
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000257 write(TUPLE + PUT + `d` + '\n')
Guido van Rossuma48061a1995-01-10 00:31:14 +0000258 self.memo[d] = object
259 dispatch[TupleType] = save_tuple
260
261 def save_list(self, object):
262 d = id(object)
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000263 write = self.write
264 save = self.save
265 write(MARK)
Guido van Rossuma48061a1995-01-10 00:31:14 +0000266 n = len(object)
267 for k in range(n):
268 item = object[k]
269 if not safe(item):
270 break
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000271 save(item)
Guido van Rossuma48061a1995-01-10 00:31:14 +0000272 else:
273 k = n
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000274 write(LIST + PUT + `d` + '\n')
Guido van Rossuma48061a1995-01-10 00:31:14 +0000275 self.memo[d] = object
276 for k in range(k, n):
277 item = object[k]
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000278 save(item)
279 write(APPEND)
Guido van Rossuma48061a1995-01-10 00:31:14 +0000280 dispatch[ListType] = save_list
281
282 def save_dict(self, object):
283 d = id(object)
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000284 write = self.write
285 save = self.save
286 write(MARK)
Guido van Rossuma48061a1995-01-10 00:31:14 +0000287 items = object.items()
288 n = len(items)
289 for k in range(n):
290 key, value = items[k]
291 if not safe(key) or not safe(value):
292 break
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000293 save(key)
294 save(value)
Guido van Rossuma48061a1995-01-10 00:31:14 +0000295 else:
296 k = n
297 self.write(DICT + PUT + `d` + '\n')
298 self.memo[d] = object
299 for k in range(k, n):
300 key, value = items[k]
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000301 save(key)
302 save(value)
303 write(SETITEM)
Guido van Rossuma48061a1995-01-10 00:31:14 +0000304 dispatch[DictionaryType] = save_dict
305
306 def save_inst(self, object):
307 d = id(object)
308 cls = object.__class__
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000309 write = self.write
310 save = self.save
Guido van Rossuma48061a1995-01-10 00:31:14 +0000311 module = whichmodule(cls)
312 name = cls.__name__
313 if hasattr(object, '__getinitargs__'):
314 args = object.__getinitargs__()
315 len(args) # XXX Assert it's a sequence
316 else:
317 args = ()
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000318 write(MARK)
Guido van Rossuma48061a1995-01-10 00:31:14 +0000319 for arg in args:
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000320 save(arg)
321 write(INST + module + '\n' + name + '\n' +
322 PUT + `d` + '\n')
Guido van Rossuma48061a1995-01-10 00:31:14 +0000323 self.memo[d] = object
324 try:
325 getstate = object.__getstate__
326 except AttributeError:
327 stuff = object.__dict__
328 else:
329 stuff = getstate()
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000330 save(stuff)
331 write(BUILD)
Guido van Rossuma48061a1995-01-10 00:31:14 +0000332 dispatch[InstanceType] = save_inst
333
Guido van Rossum0c891ce1995-03-14 15:09:05 +0000334 def save_class(self, object):
335 d = id(object)
336 module = whichmodule(object)
337 name = object.__name__
338 self.write(CLASS + module + '\n' + name + '\n' +
339 PUT + `d` + '\n')
340 dispatch[ClassType] = save_class
341
Guido van Rossuma48061a1995-01-10 00:31:14 +0000342
343classmap = {}
344
345def whichmodule(cls):
346 """Figure out the module in which a class occurs.
347
348 Search sys.modules for the module.
349 Cache in classmap.
350 Return a module name.
351 If the class cannot be found, return __main__.
352 """
353 if classmap.has_key(cls):
354 return classmap[cls]
355 import sys
356 clsname = cls.__name__
357 for name, module in sys.modules.items():
Guido van Rossumf71c79b1995-06-22 18:51:23 +0000358 if name != '__main__' and \
Guido van Rossuma48061a1995-01-10 00:31:14 +0000359 hasattr(module, clsname) and \
360 getattr(module, clsname) is cls:
361 break
362 else:
363 name = '__main__'
364 classmap[cls] = name
365 return name
366
367
368class Unpickler:
369
370 def __init__(self, file):
371 self.readline = file.readline
372 self.read = file.read
373 self.memo = {}
374
375 def load(self):
376 self.mark = ['spam'] # Any new unique object
377 self.stack = []
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000378 self.append = self.stack.append
379 read = self.read
380 dispatch = self.dispatch
Guido van Rossuma48061a1995-01-10 00:31:14 +0000381 try:
382 while 1:
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000383 key = read(1)
384 dispatch[key](self)
Guido van Rossuma48061a1995-01-10 00:31:14 +0000385 except STOP, value:
386 return value
387
388 def marker(self):
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000389 stack = self.stack
390 mark = self.mark
391 k = len(stack)-1
392 while stack[k] is not mark: k = k-1
Guido van Rossuma48061a1995-01-10 00:31:14 +0000393 return k
394
395 dispatch = {}
396
Guido van Rossum7b5430f1995-03-04 22:25:21 +0000397 def load_eof(self):
398 raise EOFError
399 dispatch[''] = load_eof
400
Guido van Rossuma48061a1995-01-10 00:31:14 +0000401 def load_persid(self):
402 pid = self.readline()[:-1]
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000403 self.append(self.persistent_load(pid))
Guido van Rossuma48061a1995-01-10 00:31:14 +0000404 dispatch[PERSID] = load_persid
405
406 def load_none(self):
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000407 self.append(None)
Guido van Rossuma48061a1995-01-10 00:31:14 +0000408 dispatch[NONE] = load_none
409
Guido van Rossum78536471996-04-12 13:36:27 +0000410 def load_int(self):
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000411 self.append(string.atoi(self.readline()[:-1], 0))
Guido van Rossum78536471996-04-12 13:36:27 +0000412 dispatch[INT] = load_int
413
414 def load_long(self):
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000415 self.append(string.atol(self.readline()[:-1], 0))
Guido van Rossum78536471996-04-12 13:36:27 +0000416 dispatch[LONG] = load_long
417
418 def load_float(self):
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000419 self.append(string.atof(self.readline()[:-1]))
Guido van Rossum78536471996-04-12 13:36:27 +0000420 dispatch[FLOAT] = load_float
421
422 def load_string(self):
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000423 self.append(eval(self.readline()[:-1],
424 {'__builtins__': {}})) # Let's be careful
Guido van Rossum78536471996-04-12 13:36:27 +0000425 dispatch[STRING] = load_string
Guido van Rossuma48061a1995-01-10 00:31:14 +0000426
427 def load_tuple(self):
428 k = self.marker()
429 self.stack[k:] = [tuple(self.stack[k+1:])]
430 dispatch[TUPLE] = load_tuple
431
432 def load_list(self):
433 k = self.marker()
434 self.stack[k:] = [self.stack[k+1:]]
435 dispatch[LIST] = load_list
436
437 def load_dict(self):
438 k = self.marker()
439 d = {}
440 items = self.stack[k+1:]
441 for i in range(0, len(items), 2):
442 key = items[i]
443 value = items[i+1]
444 d[key] = value
445 self.stack[k:] = [d]
446 dispatch[DICT] = load_dict
447
448 def load_inst(self):
449 k = self.marker()
450 args = tuple(self.stack[k+1:])
451 del self.stack[k:]
452 module = self.readline()[:-1]
453 name = self.readline()[:-1]
Guido van Rossum0c891ce1995-03-14 15:09:05 +0000454 klass = self.find_class(module, name)
455 value = apply(klass, args)
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000456 self.append(value)
Guido van Rossum0c891ce1995-03-14 15:09:05 +0000457 dispatch[INST] = load_inst
458
459 def load_class(self):
460 module = self.readline()[:-1]
461 name = self.readline()[:-1]
462 klass = self.find_class(module, name)
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000463 self.append(klass)
Guido van Rossum0c891ce1995-03-14 15:09:05 +0000464 return klass
465 dispatch[CLASS] = load_class
466
467 def find_class(self, module, name):
Guido van Rossuma48061a1995-01-10 00:31:14 +0000468 env = {}
469 try:
470 exec 'from %s import %s' % (module, name) in env
471 except ImportError:
472 raise SystemError, \
473 "Failed to import class %s from module %s" % \
474 (name, module)
Guido van Rossum0c891ce1995-03-14 15:09:05 +0000475 klass = env[name]
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000476 # if type(klass) != ClassType:
477 if (type(klass) is FunctionType or
478 type(klass) is BuiltinFunctionType):
Guido van Rossum0c891ce1995-03-14 15:09:05 +0000479 raise SystemError, \
480 "Imported object %s from module %s is not a class" % \
481 (name, module)
482 return klass
Guido van Rossuma48061a1995-01-10 00:31:14 +0000483
484 def load_pop(self):
Guido van Rossum0c891ce1995-03-14 15:09:05 +0000485 del self.stack[-1]
Guido van Rossuma48061a1995-01-10 00:31:14 +0000486 dispatch[POP] = load_pop
487
488 def load_dup(self):
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000489 self.append(stack[-1])
Guido van Rossuma48061a1995-01-10 00:31:14 +0000490 dispatch[DUP] = load_dup
491
492 def load_get(self):
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000493 self.append(self.memo[self.readline()[:-1]])
Guido van Rossuma48061a1995-01-10 00:31:14 +0000494 dispatch[GET] = load_get
495
496 def load_put(self):
Guido van Rossum78536471996-04-12 13:36:27 +0000497 self.memo[self.readline()[:-1]] = self.stack[-1]
Guido van Rossuma48061a1995-01-10 00:31:14 +0000498 dispatch[PUT] = load_put
499
500 def load_append(self):
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000501 stack = self.stack
502 value = stack[-1]
503 del stack[-1]
504 list = stack[-1]
Guido van Rossuma48061a1995-01-10 00:31:14 +0000505 list.append(value)
506 dispatch[APPEND] = load_append
507
508 def load_setitem(self):
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000509 stack = self.stack
510 value = stack[-1]
511 key = stack[-2]
512 del stack[-2:]
513 dict = stack[-1]
Guido van Rossuma48061a1995-01-10 00:31:14 +0000514 dict[key] = value
515 dispatch[SETITEM] = load_setitem
516
517 def load_build(self):
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000518 stack = self.stack
519 value = stack[-1]
520 del stack[-1]
521 inst = stack[-1]
Guido van Rossuma48061a1995-01-10 00:31:14 +0000522 try:
523 setstate = inst.__setstate__
524 except AttributeError:
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000525 instdict = inst.__dict__
Guido van Rossuma48061a1995-01-10 00:31:14 +0000526 for key in value.keys():
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000527 instdict[key] = value[key]
Guido van Rossuma48061a1995-01-10 00:31:14 +0000528 else:
529 setstate(value)
530 dispatch[BUILD] = load_build
531
532 def load_mark(self):
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000533 self.append(self.mark)
Guido van Rossuma48061a1995-01-10 00:31:14 +0000534 dispatch[MARK] = load_mark
535
536 def load_stop(self):
537 value = self.stack[-1]
538 del self.stack[-1]
539 raise STOP, value
540 dispatch[STOP] = load_stop
541
542
Guido van Rossum0c891ce1995-03-14 15:09:05 +0000543# Shorthands
544
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000545from StringIO import StringIO
546
Guido van Rossum0c891ce1995-03-14 15:09:05 +0000547def dump(object, file):
548 Pickler(file).dump(object)
549
550def dumps(object):
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000551 file = StringIO()
Guido van Rossum0c891ce1995-03-14 15:09:05 +0000552 Pickler(file).dump(object)
553 return file.getvalue()
554
555def load(file):
556 return Unpickler(file).load()
557
558def loads(str):
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000559 file = StringIO(str)
Guido van Rossum0c891ce1995-03-14 15:09:05 +0000560 return Unpickler(file).load()
561
562
563# The rest is used for testing only
564
Guido van Rossuma48061a1995-01-10 00:31:14 +0000565class C:
566 def __cmp__(self, other):
567 return cmp(self.__dict__, other.__dict__)
568
569def test():
570 fn = 'pickle_tmp'
571 c = C()
572 c.foo = 1
Guido van Rossum955c5d11996-05-15 22:49:57 +0000573 c.bar = 2L
Guido van Rossumc7c5e691996-07-22 22:26:07 +0000574 x = [0, 1, 2, 3]
Guido van Rossuma48061a1995-01-10 00:31:14 +0000575 y = ('abc', 'abc', c, c)
576 x.append(y)
577 x.append(y)
578 x.append(5)
579 f = open(fn, 'w')
580 F = Pickler(f)
581 F.dump(x)
582 f.close()
583 f = open(fn, 'r')
584 U = Unpickler(f)
585 x2 = U.load()
586 print x
587 print x2
588 print x == x2
589 print map(id, x)
590 print map(id, x2)
591 print F.memo
592 print U.memo
593
594if __name__ == '__main__':
595 test()