if rv isNotImplemented: # Check the type dispatch table t = type(obj) f = self.dispatch.get(t) if f isnotNone: f(self, obj) # Call unbound method with explicit self return
# Check private dispatch table if any, or else # copyreg.dispatch_table reduce = getattr(self, 'dispatch_table', dispatch_table).get(t) if reduce isnotNone: rv = reduce(obj) else: # Check for a class with a custom metaclass; treat as regular # class ifissubclass(t, type): self.save_global(obj) return
# Check for a __reduce_ex__ method, fall back to __reduce__ reduce = getattr(obj, "__reduce_ex__", None) if reduce isnotNone: rv = reduce(self.proto) else: reduce = getattr(obj, "__reduce__", None) if reduce isnotNone: rv = reduce() else: raise PicklingError("Can't pickle %r object: %r" % (t.__name__, obj))
# Check for string returned by reduce(), meaning "save as global" ifisinstance(rv, str): self.save_global(obj, rv) return
# Assert that reduce() returned a tuple ifnotisinstance(rv, tuple): raise PicklingError("%s must return string or tuple" % reduce)
# Assert that it returned an appropriately sized tuple l = len(rv) ifnot (2 <= l <= 6): raise PicklingError("Tuple returned by %s must have " "two to six elements" % reduce)
# Save the reduce() output and finally memoize the object self.save_reduce(obj=obj, *rv)
检查pid
Check the memo
1 2 3 4
x = self.memo.get(id(obj)) ifx is not None: self.write(self.get(x[0])) return
if rv isNotImplemented: # Check the type dispatch table # 获取对象 obj 的类型 t = type(obj) # 查找该类型 t 对应的处理方法 f = self.dispatch.get(t) if f isnotNone: f(self, obj) # Call unbound method with explicit self return
1.save_dict(self, obj)
t:dict
f:save_dict
字典序列化
1 2 3 4 5 6 7 8 9 10 11 12 13
defsave_dict(self, obj):
ifself.bin: self.write(EMPTY_DICT) b'}' else: # proto 0 -- can't use EMPTY_DICT self.write(MARK + DICT)
def _batch_setitems(self, items): # Helper to batch up SETITEMS sequences; proto >= 1 only save = self.save write = self.write # self.bin是true ifnot self.bin: for k, v initems: save(k) save(v) write(SETITEM) return
it = iter(items) while True: tmp = list(islice(it, self._BATCHSIZE)) n = len(tmp) if n > 1: write(MARK) for k, v in tmp: save(k) save(v) write(SETITEMS) elif n: pdb.set_trace() k, v = tmp[0] save(k) save(v) write(SETITEM) # else tmp is empty, and we're done if n < self._BATCHSIZE: return