##// END OF EJS Templates
Make comm manager (mostly) independent of InteractiveShell...
Make comm manager (mostly) independent of InteractiveShell This makes it possible to use comms from wrapper kernels, without instantiating the full IPython shell machinery. The one remaining place where we need a reference to shell is to fire pre_execute and post_execute hooks (which are needed to get mpl figures right). This is a pure IPythonism, that it should be safe to ignore if shell is not set.

File last commit:

r17044:65852b38
r17964:a59dfd02
Show More
serialize.py
185 lines | 5.9 KiB | text/x-python | PythonLexer
MinRK
add pickleutil.PICKLE_PROTOCOL...
r17044 """serialization utilities for apply messages"""
MinRK
move apply serialization into zmq.serialize
r6788
MinRK
add pickleutil.PICKLE_PROTOCOL...
r17044 # Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
MinRK
move apply serialization into zmq.serialize
r6788
try:
import cPickle
pickle = cPickle
except:
cPickle = None
import pickle
# IPython imports
from IPython.utils import py3compat
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133 from IPython.utils.data import flatten
MinRK
better serialization for parallel code...
r7967 from IPython.utils.pickleutil import (
MinRK
use istype instead of isinstance for canning tuples/lists...
r9712 can, uncan, can_sequence, uncan_sequence, CannedObject,
MinRK
add pickleutil.PICKLE_PROTOCOL...
r17044 istype, sequence_types, PICKLE_PROTOCOL,
MinRK
remove unused newserialized imports
r7969 )
MinRK
move apply serialization into zmq.serialize
r6788
if py3compat.PY3:
buffer = memoryview
#-----------------------------------------------------------------------------
# Serialization Functions
#-----------------------------------------------------------------------------
MinRK
allow configuration of item/buffer thresholds
r8033 # default values for the thresholds:
MinRK
better serialization for parallel code...
r7967 MAX_ITEMS = 64
MinRK
allow configuration of item/buffer thresholds
r8033 MAX_BYTES = 1024
MinRK
better serialization for parallel code...
r7967
MinRK
allow configuration of item/buffer thresholds
r8033 def _extract_buffers(obj, threshold=MAX_BYTES):
MinRK
better serialization for parallel code...
r7967 """extract buffers larger than a certain threshold"""
buffers = []
if isinstance(obj, CannedObject) and obj.buffers:
for i,buf in enumerate(obj.buffers):
if len(buf) > threshold:
# buffer larger than threshold, prevent pickling
obj.buffers[i] = None
buffers.append(buf)
elif isinstance(buf, buffer):
# buffer too small for separate send, coerce to bytes
# because pickling buffer objects just results in broken pointers
obj.buffers[i] = bytes(buf)
return buffers
def _restore_buffers(obj, buffers):
"""restore buffers extracted by """
if isinstance(obj, CannedObject) and obj.buffers:
for i,buf in enumerate(obj.buffers):
if buf is None:
obj.buffers[i] = buffers.pop(0)
MinRK
allow configuration of item/buffer thresholds
r8033 def serialize_object(obj, buffer_threshold=MAX_BYTES, item_threshold=MAX_ITEMS):
MinRK
move apply serialization into zmq.serialize
r6788 """Serialize an object into a list of sendable buffers.
Parameters
----------
obj : object
The object to be serialized
MinRK
allow configuration of item/buffer thresholds
r8033 buffer_threshold : int
MinRK
better serialization for parallel code...
r7967 The threshold (in bytes) for pulling out data buffers
to avoid pickling them.
MinRK
allow configuration of item/buffer thresholds
r8033 item_threshold : int
The maximum number of items over which canning will iterate.
Containers (lists, dicts) larger than this will be pickled without
introspection.
MinRK
move apply serialization into zmq.serialize
r6788
Returns
-------
MinRK
better serialization for parallel code...
r7967 [bufs] : list of buffers representing the serialized object.
MinRK
move apply serialization into zmq.serialize
r6788 """
MinRK
better serialization for parallel code...
r7967 buffers = []
MinRK
use istype instead of isinstance for canning tuples/lists...
r9712 if istype(obj, sequence_types) and len(obj) < item_threshold:
MinRK
better serialization for parallel code...
r7967 cobj = can_sequence(obj)
for c in cobj:
MinRK
allow configuration of item/buffer thresholds
r8033 buffers.extend(_extract_buffers(c, buffer_threshold))
MinRK
use istype instead of isinstance for canning tuples/lists...
r9712 elif istype(obj, dict) and len(obj) < item_threshold:
MinRK
better serialization for parallel code...
r7967 cobj = {}
Thomas Kluyver
Remove uses of iterkeys
r13360 for k in sorted(obj):
MinRK
better serialization for parallel code...
r7967 c = can(obj[k])
MinRK
allow configuration of item/buffer thresholds
r8033 buffers.extend(_extract_buffers(c, buffer_threshold))
MinRK
better serialization for parallel code...
r7967 cobj[k] = c
MinRK
move apply serialization into zmq.serialize
r6788 else:
MinRK
better serialization for parallel code...
r7967 cobj = can(obj)
MinRK
allow configuration of item/buffer thresholds
r8033 buffers.extend(_extract_buffers(cobj, buffer_threshold))
MinRK
better serialization for parallel code...
r7967
MinRK
add pickleutil.PICKLE_PROTOCOL...
r17044 buffers.insert(0, pickle.dumps(cobj, PICKLE_PROTOCOL))
MinRK
better serialization for parallel code...
r7967 return buffers
def unserialize_object(buffers, g=None):
"""reconstruct an object serialized by serialize_object from data buffers.
Parameters
----------
bufs : list of buffers/bytes
g : globals to be used when uncanning
Returns
-------
(newobj, bufs) : unpacked object, and the list of remaining unused buffers.
"""
bufs = list(buffers)
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133 pobj = bufs.pop(0)
if not isinstance(pobj, bytes):
# a zmq message
pobj = bytes(pobj)
canned = pickle.loads(pobj)
MinRK
use istype instead of isinstance for canning tuples/lists...
r9712 if istype(canned, sequence_types) and len(canned) < MAX_ITEMS:
MinRK
better serialization for parallel code...
r7967 for c in canned:
_restore_buffers(c, bufs)
newobj = uncan_sequence(canned, g)
Stephan Rave
Use istype() when checking if canned object is a dict...
r12199 elif istype(canned, dict) and len(canned) < MAX_ITEMS:
MinRK
move apply serialization into zmq.serialize
r6788 newobj = {}
Thomas Kluyver
Remove uses of iterkeys
r13360 for k in sorted(canned):
MinRK
better serialization for parallel code...
r7967 c = canned[k]
_restore_buffers(c, bufs)
newobj[k] = uncan(c, g)
MinRK
move apply serialization into zmq.serialize
r6788 else:
MinRK
better serialization for parallel code...
r7967 _restore_buffers(canned, bufs)
newobj = uncan(canned, g)
return newobj, bufs
MinRK
move apply serialization into zmq.serialize
r6788
MinRK
allow configuration of item/buffer thresholds
r8033 def pack_apply_message(f, args, kwargs, buffer_threshold=MAX_BYTES, item_threshold=MAX_ITEMS):
MinRK
move apply serialization into zmq.serialize
r6788 """pack up a function, args, and kwargs to be sent over the wire
MinRK
allow configuration of item/buffer thresholds
r8033
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133 Each element of args/kwargs will be canned for special treatment,
but inspection will not go any deeper than that.
Any object whose data is larger than `threshold` will not have their data copied
(only numpy arrays and bytes/buffers support zero-copy)
Message will be a list of bytes/buffers of the format:
[ cf, pinfo, <arg_bufs>, <kwarg_bufs> ]
With length at least two + len(args) + len(kwargs)
MinRK
better serialization for parallel code...
r7967 """
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133
arg_bufs = flatten(serialize_object(arg, buffer_threshold, item_threshold) for arg in args)
kw_keys = sorted(kwargs.keys())
kwarg_bufs = flatten(serialize_object(kwargs[key], buffer_threshold, item_threshold) for key in kw_keys)
info = dict(nargs=len(args), narg_bufs=len(arg_bufs), kw_keys=kw_keys)
MinRK
add pickleutil.PICKLE_PROTOCOL...
r17044 msg = [pickle.dumps(can(f), PICKLE_PROTOCOL)]
msg.append(pickle.dumps(info, PICKLE_PROTOCOL))
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133 msg.extend(arg_bufs)
msg.extend(kwarg_bufs)
MinRK
move apply serialization into zmq.serialize
r6788 return msg
def unpack_apply_message(bufs, g=None, copy=True):
"""unpack f,args,kwargs from buffers packed by pack_apply_message()
Returns: original f,args,kwargs"""
bufs = list(bufs) # allow us to pop
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133 assert len(bufs) >= 2, "not enough buffers!"
MinRK
move apply serialization into zmq.serialize
r6788 if not copy:
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133 for i in range(2):
MinRK
move apply serialization into zmq.serialize
r6788 bufs[i] = bufs[i].bytes
MinRK
better serialization for parallel code...
r7967 f = uncan(pickle.loads(bufs.pop(0)), g)
MinRK
serialize elements of args/kwargs in pack_apply message...
r8133 info = pickle.loads(bufs.pop(0))
arg_bufs, kwarg_bufs = bufs[:info['narg_bufs']], bufs[info['narg_bufs']:]
args = []
for i in range(info['nargs']):
arg, arg_bufs = unserialize_object(arg_bufs, g)
args.append(arg)
args = tuple(args)
assert not arg_bufs, "Shouldn't be any arg bufs left over"
kwargs = {}
for key in info['kw_keys']:
kwarg, kwarg_bufs = unserialize_object(kwarg_bufs, g)
kwargs[key] = kwarg
assert not kwarg_bufs, "Shouldn't be any kwarg bufs left over"
MinRK
move apply serialization into zmq.serialize
r6788
return f,args,kwargs