title: How to access multiprocessing.Manager().Namespace element remotely via SyncManager?
body: <p>No matter how hard I read the docs, I fail to understand how to use a SyncManager to access remotely an item of a multiprocessing Namespace.</p>
  <p>Please note the code below is the shortest possible to demonstrate what works and what fails. The crux of my problem lies in the calls to <code>register</code>, which I fail to properly understand how to use.</p>
  <p>The example below comprises of two parts (both in the same file <code>mp-example.py</code>): a server and a client. For the client part to do its work, the server part must be running (in another terminal/screen).</p>
  <h1>First, the code that works:</h1>
  <pre><code>#!/usr/bin/env python3
  
  import os
  import sys
  import multiprocessing as mp
  import multiprocessing.managers as mpm
  import queue
  import socket
  import contextlib
  from contextlib import contextmanager
  
  def get_ip():
      with contextlib.closing(socket.socket(socket.AF_INET, socket.SOCK_DGRAM)) as s:
          s.connect(('192.168.17.1', 80))
          return s.getsockname()[0]
  
  def get_free_port():
      with contextlib.closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
          s.bind(('', 0))
          s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
          return s.getsockname()[1]
  
  def startserver(name):
      # Find a free port for the SyncManager
      newportnumber = get_free_port()
      Server = {'address': (get_ip(), newportnumber), 'authkey': b'mptest'}
  
      # Save data to file
      serverdata_filename = f'mpSERVERDATA.txt'
      with open(serverdata_filename, 'wt', encoding=&quot;utf-8&quot;) as serverdata_file:
          print(Server, file=serverdata_file)
          print(Server)
  
      # On the server, we do not need our own IP address
      Server['address'] = ('', newportnumber)
  
      # Set up server:
      #   define a multiprocessing manager
      #   define a multipprocessing namespace
      #   define a Value item in the namespace
      #   define a Value item outside the namespace
      #   define a multiprocessing syncmanager
      #   start the syncmanager
      #   register both the namespace and the value outside the namespace
      #   set values
      #   initialise a different process
      #   print the values
      #   run the other process &amp; wait for completion
      #   print the values
      #   read standard input &amp; print the values (waiting for a remote process connection)
  
      m = mp.Manager()
      m.name = 'mp.Manager: ' + name
  
      with m:
          ns = m.Namespace()
          ns.name = 'm.Namespace: ' + name
          ns.yv = m.Value(int, 0)
          yv = m.Value(int, 0)
  
          bm = mpm.SyncManager(**Server)
          bm.name = 'mpm.SyncManager: ' + name
  
          #bm.register('ns', callable=lambda: ns, proxytype=mpm.NamespaceProxy,
          #            exposed=('__getattribute__', '__setattr__', '__delattr__', 'yv')
          #           )
          # The above has not made any difference
          bm.register('ns', callable=lambda: ns, proxytype=mpm.NamespaceProxy)
          bm.register('yv', callable=lambda: yv, proxytype=mpm.ValueProxy)
  
          with bm:
              yv.value = 99
              ns.yv = 999
  
              def f(n, y):
                  n.yv += 222
                  y.value += 33
  
              proc = mp.Process(target=f, args=(ns, yv))
              print(f'yv={yv}, ns.yv={ns.yv}')
              proc.start()
              proc.join()
              proc.terminate()
              print(f'yv={yv}, ns.yv={ns.yv}, ns={ns}')
              print('Waiting for input (waiting for client), press CTRL-D to end')
              for line in sys.stdin:
                  print(f'yv={yv}, ns.yv={ns.yv}, ns={ns}')
                  print('Waiting for input (waiting for client), press CTRL-D to end')
  
  elif sys.argv[1] == 'server' and len(sys.argv) == 3:
      startserver(sys.argv[2])
  elif sys.argv[1] == 'client' and len(sys.argv) == 3:
      startclient(sys.argv[2])
  </code></pre>
  <p>The code above does what I expect when run on its own:</p>
  <pre><code>&gt; python3 mp-example.py server test
  {'address': ('192.168.17.10', 50793), 'authkey': b'mptest'}
  yv=Value(&lt;class 'int'&gt;, 99), ns.yv=999
  yv=Value(&lt;class 'int'&gt;, 132), ns.yv=1221, ns=Namespace(name='m.Namespace: test', yv=1221)
  Waiting for input (waiting for client), press CTRL-D to end
  </code></pre>
  <h1>Next, the bit that does not work:</h1>
  <p>The code below works up to a point, but fails when trying to access the Value item <code>yv</code> within the Namespace.</p>
  <p>Code:</p>
  <pre><code>def startclient(name):
      # retrieve server identification from file
      serverdata_filename = f'mpSERVERDATA.txt'
      with open(serverdata_filename, 'rt', encoding=&quot;utf-8&quot;) as serverdata_file:
          Server = eval(serverdata_file.read())
          print(Server)
  
      bm = mpm.SyncManager(**Server)
      bm.register('yv', proxytype=mpm.ValueProxy)
      bm.register('ns', proxytype=mpm.NamespaceProxy)
      bm.connect()
  
      yv = bm.yv()
      print(f'yv={yv.value}')
      yv.value += 55
      print(f'yv={yv.value}')
  
      ns = bm.ns()
      print(f'ns={ns}')
      print(f'ns.yv={ns.yv}')
      ns.yv += 666
      print(f'ns.yv={ns.yv}')
  </code></pre>
  <p>Output:</p>
  <pre><code>&gt; python3 mp-example.py client test
  {'address': ('192.168.17.10', 50793), 'authkey': b'mptest'}
  yv=627
  yv=682
  ['_Client', '__class__', '__deepcopy__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_address_to_local', '_after_fork', '_authkey', '_callmethod', '_close', '_connect', '_decref', '_exposed_', '_getvalue', '_id', '_idset', '_incref', '_manager', '_mutex', '_owned_by_manager', '_serializer', '_tls', '_token']
  Help on method _getvalue in module multiprocessing.managers:
  
  _getvalue() method of multiprocessing.managers.NamespaceProxy instance
      Get a copy of the value of the referent
  
  None
  ns=&lt;NamespaceProxy object, typeid 'Namespace' at 0x7f5d05689a20&gt;
  Traceback (most recent call last):
    File &quot;mp-example.py&quot;, line 333, in &lt;module&gt;
      startclient(sys.argv[2])
    File &quot;mp-example.py&quot;, line 282, in startclient
      print(f'ns.yv={ns.yv}')
    File &quot;/usr/lib/python3.6/multiprocessing/managers.py&quot;, line 1060, in __getattr__
      return callmethod('__getattribute__', (key,))
    File &quot;/usr/lib/python3.6/multiprocessing/managers.py&quot;, line 772, in _callmethod
      raise convert_to_error(kind, result)
  AttributeError: 'NamespaceProxy' object has no attribute 'yv'
  </code></pre>
  <h1>Question:</h1>
  <p>What do I need to do to access <code>ns.yv</code> in the client?</p>