proxy-objects.txt 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. .. include:: header.txt
  2. ===============
  3. Proxy objects
  4. ===============
  5. A proxy is an object which *refers* to a shared object which lives
  6. (presumably) in a different process. The shared object is said to be
  7. the *referent* of the proxy. Multiple proxy objects may have the same
  8. referent.
  9. A proxy object has methods which invoke corresponding methods of its
  10. referent (although not every method of the referent will
  11. necessarily be available through the proxy). A proxy can usually be
  12. used in most of the same ways that the its referent can::
  13. >>> from processing import Manager
  14. >>> manager = Manager()
  15. >>> l = manager.list([i*i for i in range(10)])
  16. >>> print l
  17. [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  18. >>> print repr(l)
  19. <Proxy[list] object at 0x00DFA230>
  20. >>> l[4]
  21. 16
  22. >>> l[2:5]
  23. [4, 9, 16]
  24. >>> l == [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  25. True
  26. Notice that applying `str()` to a proxy will return the
  27. representation of the referent, whereas applying `repr()` will
  28. return the representation of the proxy.
  29. An important feature of proxy objects is that they are picklable so
  30. they can be passed between processes. Note, however, that if a proxy
  31. is sent to the corresponding manager's process then unpickling it will
  32. produce the referent itself. This means, for example, that one shared
  33. object can contain a second::
  34. >>> a = manager.list()
  35. >>> b = manager.list()
  36. >>> a.append(b) # referent of `a` now contains referent of `b`
  37. >>> print a, b
  38. [[]] []
  39. >>> b.append('hello')
  40. >>> print a, b
  41. [['hello']] ['hello']
  42. Some proxy methods return a proxy for an iterator. In particular list
  43. and dictionary proxies are iterables so they can be used with the
  44. `for` statement::
  45. >>> a = manager.dict([(i*i, i) for i in range(10)])
  46. >>> for key in a:
  47. ... print '<%r,%r>' % (key, a[key]),
  48. ...
  49. <0,0> <1,1> <4,2> <81,9> <64,8> <9,3> <16,4> <49,7> <25,5> <36,6>
  50. .. note::
  51. Although `list` and `dict` proxy objects are iterable, it will be
  52. much more efficient to iterate over a *copy* of the referent, for
  53. example ::
  54. for item in some_list[:]:
  55. ...
  56. and ::
  57. for key in some_dict.keys():
  58. ...
  59. Methods of `BaseProxy`
  60. ======================
  61. Proxy objects are instances of subclasses of `BaseProxy`. The only
  62. semi-public methods of `BaseProxy` are the following:
  63. `_callMethod(methodname, args=(), kwds={})`
  64. Call and return the result of a method of the proxy's referent.
  65. If `proxy` is a proxy whose referent is `obj` then the
  66. expression
  67. `proxy._callMethod(methodname, args, kwds)`
  68. will evaluate the expression
  69. `getattr(obj, methodname)(*args, **kwds)` |spaces| _`(*)`
  70. in the manager's process.
  71. The returned value will be either a copy of the result of
  72. `(*)`_ or if the result is an unpicklable iterator then a
  73. proxy for the iterator.
  74. If an exception is raised by `(*)`_ then then is re-raised by
  75. `_callMethod()`. If some other exception is raised in the
  76. manager's process then this is converted into a `RemoteError`
  77. exception and is raised by `_callMethod()`.
  78. Note in particular that an exception will be raised if
  79. `methodname` has not been *exposed* --- see the `exposed`
  80. argument to `CreatorMethod
  81. <manager-objects.html#customized-managers>`_.
  82. `_getValue()`
  83. Return a copy of the referent.
  84. If the referent is unpicklable then this will raise an exception.
  85. `__repr__`
  86. Return a representation of the proxy object.
  87. `__str__`
  88. Return the representation of the referent.
  89. Cleanup
  90. =======
  91. A proxy object uses a weakref callback so that when it gets garbage
  92. collected it deregisters itself from the manager which owns its
  93. referent.
  94. A shared object gets deleted from the manager process when there
  95. are no longer any proxies referring to it.
  96. Examples
  97. ========
  98. An example of the usage of `_callMethod()`::
  99. >>> l = manager.list(range(10))
  100. >>> l._callMethod('__getslice__', (2, 7)) # equiv to `l[2:7]`
  101. [2, 3, 4, 5, 6]
  102. >>> l._callMethod('__iter__') # equiv to `iter(l)`
  103. <Proxy[iter] object at 0x00DFAFF0>
  104. >>> l._callMethod('__getitem__', (20,)) # equiv to `l[20]`
  105. Traceback (most recent call last):
  106. ...
  107. IndexError: list index out of range
  108. As an example definition of a subclass of BaseProxy, the proxy type
  109. used for iterators is the following::
  110. class IteratorProxy(BaseProxy):
  111. def __iter__(self):
  112. return self
  113. def next(self):
  114. return self._callMethod('next')
  115. .. _Prev: manager-objects.html
  116. .. _Up: processing-ref.html
  117. .. _Next: pool-objects.html