.. include:: header.txt =============== Proxy objects =============== A proxy is an object which *refers* to a shared object which lives (presumably) in a different process. The shared object is said to be the *referent* of the proxy. Multiple proxy objects may have the same referent. A proxy object has methods which invoke corresponding methods of its referent (although not every method of the referent will necessarily be available through the proxy). A proxy can usually be used in most of the same ways that the its referent can:: >>> from processing import Manager >>> manager = Manager() >>> l = manager.list([i*i for i in range(10)]) >>> print l [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> print repr(l) >>> l[4] 16 >>> l[2:5] [4, 9, 16] >>> l == [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] True Notice that applying `str()` to a proxy will return the representation of the referent, whereas applying `repr()` will return the representation of the proxy. An important feature of proxy objects is that they are picklable so they can be passed between processes. Note, however, that if a proxy is sent to the corresponding manager's process then unpickling it will produce the referent itself. This means, for example, that one shared object can contain a second:: >>> a = manager.list() >>> b = manager.list() >>> a.append(b) # referent of `a` now contains referent of `b` >>> print a, b [[]] [] >>> b.append('hello') >>> print a, b [['hello']] ['hello'] Some proxy methods return a proxy for an iterator. In particular list and dictionary proxies are iterables so they can be used with the `for` statement:: >>> a = manager.dict([(i*i, i) for i in range(10)]) >>> for key in a: ... print '<%r,%r>' % (key, a[key]), ... <0,0> <1,1> <4,2> <81,9> <64,8> <9,3> <16,4> <49,7> <25,5> <36,6> .. note:: Although `list` and `dict` proxy objects are iterable, it will be much more efficient to iterate over a *copy* of the referent, for example :: for item in some_list[:]: ... and :: for key in some_dict.keys(): ... Methods of `BaseProxy` ====================== Proxy objects are instances of subclasses of `BaseProxy`. The only semi-public methods of `BaseProxy` are the following: `_callMethod(methodname, args=(), kwds={})` Call and return the result of a method of the proxy's referent. If `proxy` is a proxy whose referent is `obj` then the expression `proxy._callMethod(methodname, args, kwds)` will evaluate the expression `getattr(obj, methodname)(*args, **kwds)` |spaces| _`(*)` in the manager's process. The returned value will be either a copy of the result of `(*)`_ or if the result is an unpicklable iterator then a proxy for the iterator. If an exception is raised by `(*)`_ then then is re-raised by `_callMethod()`. If some other exception is raised in the manager's process then this is converted into a `RemoteError` exception and is raised by `_callMethod()`. Note in particular that an exception will be raised if `methodname` has not been *exposed* --- see the `exposed` argument to `CreatorMethod `_. `_getValue()` Return a copy of the referent. If the referent is unpicklable then this will raise an exception. `__repr__` Return a representation of the proxy object. `__str__` Return the representation of the referent. Cleanup ======= A proxy object uses a weakref callback so that when it gets garbage collected it deregisters itself from the manager which owns its referent. A shared object gets deleted from the manager process when there are no longer any proxies referring to it. Examples ======== An example of the usage of `_callMethod()`:: >>> l = manager.list(range(10)) >>> l._callMethod('__getslice__', (2, 7)) # equiv to `l[2:7]` [2, 3, 4, 5, 6] >>> l._callMethod('__iter__') # equiv to `iter(l)` >>> l._callMethod('__getitem__', (20,)) # equiv to `l[20]` Traceback (most recent call last): ... IndexError: list index out of range As an example definition of a subclass of BaseProxy, the proxy type used for iterators is the following:: class IteratorProxy(BaseProxy): def __iter__(self): return self def next(self): return self._callMethod('next') .. _Prev: manager-objects.html .. _Up: processing-ref.html .. _Next: pool-objects.html