proxy-objects.html 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  6. <meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
  7. <title>Proxy objects</title>
  8. <link rel="stylesheet" href="html4css1.css" type="text/css" />
  9. </head>
  10. <body>
  11. <div class="header">
  12. <a class="reference" href="manager-objects.html">Prev</a> &nbsp; &nbsp; &nbsp; &nbsp; <a class="reference" href="processing-ref.html">Up</a> &nbsp; &nbsp; &nbsp; &nbsp; <a class="reference" href="pool-objects.html">Next</a>
  13. <hr class="header"/>
  14. </div>
  15. <div class="document" id="proxy-objects">
  16. <h1 class="title">Proxy objects</h1>
  17. <p>A proxy is an object which <em>refers</em> to a shared object which lives
  18. (presumably) in a different process. The shared object is said to be
  19. the <em>referent</em> of the proxy. Multiple proxy objects may have the same
  20. referent.</p>
  21. <p>A proxy object has methods which invoke corresponding methods of its
  22. referent (although not every method of the referent will
  23. necessarily be available through the proxy). A proxy can usually be
  24. used in most of the same ways that the its referent can:</p>
  25. <pre class="literal-block">
  26. &gt;&gt;&gt; from processing import Manager
  27. &gt;&gt;&gt; manager = Manager()
  28. &gt;&gt;&gt; l = manager.list([i*i for i in range(10)])
  29. &gt;&gt;&gt; print l
  30. [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  31. &gt;&gt;&gt; print repr(l)
  32. &lt;Proxy[list] object at 0x00DFA230&gt;
  33. &gt;&gt;&gt; l[4]
  34. 16
  35. &gt;&gt;&gt; l[2:5]
  36. [4, 9, 16]
  37. &gt;&gt;&gt; l == [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  38. True
  39. </pre>
  40. <p>Notice that applying <tt class="docutils literal"><span class="pre">str()</span></tt> to a proxy will return the
  41. representation of the referent, whereas applying <tt class="docutils literal"><span class="pre">repr()</span></tt> will
  42. return the representation of the proxy.</p>
  43. <p>An important feature of proxy objects is that they are picklable so
  44. they can be passed between processes. Note, however, that if a proxy
  45. is sent to the corresponding manager's process then unpickling it will
  46. produce the referent itself. This means, for example, that one shared
  47. object can contain a second:</p>
  48. <pre class="literal-block">
  49. &gt;&gt;&gt; a = manager.list()
  50. &gt;&gt;&gt; b = manager.list()
  51. &gt;&gt;&gt; a.append(b) # referent of `a` now contains referent of `b`
  52. &gt;&gt;&gt; print a, b
  53. [[]] []
  54. &gt;&gt;&gt; b.append('hello')
  55. &gt;&gt;&gt; print a, b
  56. [['hello']] ['hello']
  57. </pre>
  58. <p>Some proxy methods return a proxy for an iterator. In particular list
  59. and dictionary proxies are iterables so they can be used with the
  60. <tt class="docutils literal"><span class="pre">for</span></tt> statement:</p>
  61. <pre class="literal-block">
  62. &gt;&gt;&gt; a = manager.dict([(i*i, i) for i in range(10)])
  63. &gt;&gt;&gt; for key in a:
  64. ... print '&lt;%r,%r&gt;' % (key, a[key]),
  65. ...
  66. &lt;0,0&gt; &lt;1,1&gt; &lt;4,2&gt; &lt;81,9&gt; &lt;64,8&gt; &lt;9,3&gt; &lt;16,4&gt; &lt;49,7&gt; &lt;25,5&gt; &lt;36,6&gt;
  67. </pre>
  68. <div class="note">
  69. <p class="first admonition-title">Note</p>
  70. <p>Although <tt class="docutils literal"><span class="pre">list</span></tt> and <tt class="docutils literal"><span class="pre">dict</span></tt> proxy objects are iterable, it will be
  71. much more efficient to iterate over a <em>copy</em> of the referent, for
  72. example</p>
  73. <pre class="literal-block">
  74. for item in some_list[:]:
  75. ...
  76. </pre>
  77. <p>and</p>
  78. <pre class="last literal-block">
  79. for key in some_dict.keys():
  80. ...
  81. </pre>
  82. </div>
  83. <div class="section">
  84. <h1><a id="methods-of-baseproxy" name="methods-of-baseproxy">Methods of <tt class="docutils literal"><span class="pre">BaseProxy</span></tt></a></h1>
  85. <p>Proxy objects are instances of subclasses of <tt class="docutils literal"><span class="pre">BaseProxy</span></tt>. The only
  86. semi-public methods of <tt class="docutils literal"><span class="pre">BaseProxy</span></tt> are the following:</p>
  87. <blockquote>
  88. <dl class="docutils">
  89. <dt><tt class="docutils literal"><span class="pre">_callMethod(methodname,</span> <span class="pre">args=(),</span> <span class="pre">kwds={})</span></tt></dt>
  90. <dd><p class="first">Call and return the result of a method of the proxy's referent.</p>
  91. <p>If <tt class="docutils literal"><span class="pre">proxy</span></tt> is a proxy whose referent is <tt class="docutils literal"><span class="pre">obj</span></tt> then the
  92. expression</p>
  93. <blockquote>
  94. <tt class="docutils literal"><span class="pre">proxy._callMethod(methodname,</span> <span class="pre">args,</span> <span class="pre">kwds)</span></tt></blockquote>
  95. <p>will evaluate the expression</p>
  96. <blockquote>
  97. <tt class="docutils literal"><span class="pre">getattr(obj,</span> <span class="pre">methodname)(*args,</span> <span class="pre">**kwds)</span></tt> &nbsp; &nbsp; &nbsp; &nbsp; <span class="target" id="id1">(*)</span></blockquote>
  98. <p>in the manager's process.</p>
  99. <p>The returned value will be either a copy of the result of
  100. <a class="reference" href="#id1">(*)</a> or if the result is an unpicklable iterator then a
  101. proxy for the iterator.</p>
  102. <p>If an exception is raised by <a class="reference" href="#id1">(*)</a> then then is re-raised by
  103. <tt class="docutils literal"><span class="pre">_callMethod()</span></tt>. If some other exception is raised in the
  104. manager's process then this is converted into a <tt class="docutils literal"><span class="pre">RemoteError</span></tt>
  105. exception and is raised by <tt class="docutils literal"><span class="pre">_callMethod()</span></tt>.</p>
  106. <p class="last">Note in particular that an exception will be raised if
  107. <tt class="docutils literal"><span class="pre">methodname</span></tt> has not been <em>exposed</em> --- see the <tt class="docutils literal"><span class="pre">exposed</span></tt>
  108. argument to <a class="reference" href="manager-objects.html#customized-managers">CreatorMethod</a>.</p>
  109. </dd>
  110. <dt><tt class="docutils literal"><span class="pre">_getValue()</span></tt></dt>
  111. <dd><p class="first">Return a copy of the referent.</p>
  112. <p class="last">If the referent is unpicklable then this will raise an exception.</p>
  113. </dd>
  114. <dt><tt class="docutils literal"><span class="pre">__repr__</span></tt></dt>
  115. <dd>Return a representation of the proxy object.</dd>
  116. <dt><tt class="docutils literal"><span class="pre">__str__</span></tt></dt>
  117. <dd>Return the representation of the referent.</dd>
  118. </dl>
  119. </blockquote>
  120. </div>
  121. <div class="section">
  122. <h1><a id="cleanup" name="cleanup">Cleanup</a></h1>
  123. <p>A proxy object uses a weakref callback so that when it gets garbage
  124. collected it deregisters itself from the manager which owns its
  125. referent.</p>
  126. <p>A shared object gets deleted from the manager process when there
  127. are no longer any proxies referring to it.</p>
  128. </div>
  129. <div class="section">
  130. <h1><a id="examples" name="examples">Examples</a></h1>
  131. <p>An example of the usage of <tt class="docutils literal"><span class="pre">_callMethod()</span></tt>:</p>
  132. <pre class="literal-block">
  133. &gt;&gt;&gt; l = manager.list(range(10))
  134. &gt;&gt;&gt; l._callMethod('__getslice__', (2, 7)) # equiv to `l[2:7]`
  135. [2, 3, 4, 5, 6]
  136. &gt;&gt;&gt; l._callMethod('__iter__') # equiv to `iter(l)`
  137. &lt;Proxy[iter] object at 0x00DFAFF0&gt;
  138. &gt;&gt;&gt; l._callMethod('__getitem__', (20,)) # equiv to `l[20]`
  139. Traceback (most recent call last):
  140. ...
  141. IndexError: list index out of range
  142. </pre>
  143. <p>As an example definition of a subclass of BaseProxy, the proxy type
  144. used for iterators is the following:</p>
  145. <pre class="literal-block">
  146. class IteratorProxy(BaseProxy):
  147. def __iter__(self):
  148. return self
  149. def next(self):
  150. return self._callMethod('next')
  151. </pre>
  152. </div>
  153. </div>
  154. <div class="footer">
  155. <hr class="footer" />
  156. <a class="reference" href="manager-objects.html">Prev</a> &nbsp; &nbsp; &nbsp; &nbsp; <a class="reference" href="processing-ref.html">Up</a> &nbsp; &nbsp; &nbsp; &nbsp; <a class="reference" href="pool-objects.html">Next</a>
  157. </div>
  158. </body>
  159. </html>