As you have probably figured out, the problem is that manager_namespace
is actually a proxy object and inspecting its __dict__
attribute will not reveal any useful information. Therefore, there is no general solution to your problem that can work for an arbitrary Namespace proxy.
However, if you look at the documentation for multiprocessing.managers.Namespace
, you will see (in part):
A namespace object has no public methods, but does have writable attributes. Its representation shows the values of its attributes.
However, when using a proxy for a namespace object, an attribute beginning with '_' will be an attribute of the proxy and not an attribute of the referent:
So, as long as:
- Your attributes do not begin with an underscore ('_') but otherwise are legal variable names and
- The values of the attributes are not values that contain an equal sign ('=') then
You should be able to take the string representation of the Namespace proxy and with a simple regex pull out all the attribute names:
from multiprocessing import Manager
import re
# required for Windows:
if __name__ == '__main__':
manager = Manager()
manager_namespace = manager.Namespace()
manager_namespace.__setattr__('x', 1)
manager_namespace.__setattr__('y', 2)
manager_namespace.__setattr__('z', 3)
attributes = re.findall(r'\b([A-Za-z][A-Za-z_0-9]*)=', str(manager_namespace))
print(attributes)
Prints:
['x', 'y', 'z']
You could relax the condition for naming your attributes but would have to then adjust the regular expression accordingly.
So it is only under this extremely limited and possibly not very useful set of circumstances, assuming that you have control over them, that getting the attributes could be feasible.
Update
Another possibility is to use a new, customized managed class MyNamespace
(call it whatever you want) in place of Namespace
that supports a get_dict
(call it whatever you want) method that will return the dictionary of the actual namespace object:
from multiprocessing.managers import BaseManager, NamespaceProxy
class MyNamespaceManager(BaseManager):
pass
class MyNamespace:
def get_dict(self):
return self.__dict__
class MyNamespaceProxy(NamespaceProxy):
_exposed_ = ('__getattribute__', '__setattr__', '__delattr__', 'get_dict')
def get_dict(self):
return self._callmethod('get_dict')
# required for Windows:
if __name__ == '__main__':
MyNamespaceManager.register('MyNamespace', MyNamespace, MyNamespaceProxy)
with MyNamespaceManager() as manager:
ns = manager.MyNamespace()
ns.__setattr__('x', 1)
ns.__setattr__('y', 2)
ns.z = 3 # Different style of assignment
print(ns.get_dict())
Prints:
{'x': 1, 'y': 2, 'z': 3}
If you will be using the SyncManager
class because you need other built-in managed objects, for example, dict
, then:
from multiprocessing import Manager
from multiprocessing.managers import SyncManager, NamespaceProxy
class MyNamespace:
def get_dict(self):
return self.__dict__
class MyNamespaceProxy(NamespaceProxy):
_exposed_ = ('__getattribute__', '__setattr__', '__delattr__', 'get_dict')
def get_dict(self):
return self._callmethod('get_dict')
# required for Windows:
if __name__ == '__main__':
SyncManager.register('MyNamespace', MyNamespace, MyNamespaceProxy)
with Manager() as manager:
ns = manager.MyNamespace()
ns.__setattr__('x', 1)
ns.__setattr__('y', 2)
ns.z = 3 # Different style of assignment
print(ns.get_dict())