[docs] [issue35786] get_lock() method is not present for Values created using multiprocessing.Manager()

Josh Rosenberg report at bugs.python.org
Wed Aug 7 14:54:01 EDT 2019

Josh Rosenberg <shadowranger+python at gmail.com> added the comment:

Reading the docs, I'd definitely expect multiprocessing.Manager().Value to obey the same interface as multiprocessing.Value. The SyncManager docs say:

> Its methods create and return Proxy Objects for a number of commonly used data types to be synchronized across processes.

It does also say (under the linked definition for Proxy Objects):

> 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).

which implies the proxy might be more limited, but in fact the proxy is wrapping a completely different underlying class, multiprocessing.managers.Value (that has nothing to do with the class you'd get from calling multiprocessing.Value or multiprocessing.sharedctypes.Value).

It looks like there was, at some point, an attempt to make certain interfaces match; multiprocessing.managers.Value's initializer has a prototype of:

def __init__(self, typecode, value, lock=True):

(documented prototype excludes the lock argument), but AFAICT, lock is completely ignored, and typecode is stored as _typecode on the underlying Value, but otherwise ignored; the multiprocessing.managers.ValueProxy object returned by manager.Value() doesn't expose it (except insofar as you can call ._getvalue() on it to retrieve a copy of the underlying Value), and even if you get the unwrapped object, all _typecode does is change the repr; it's not used anywhere else.

It seems like SyncManager.Value is just the worst of all possible worlds; it has a prototype that (roughly) matches multiprocessing.Value/multiprocessing.sharedctypes.Value, and the limited documentation implies it serves the same function, but:

1. It effectively ignores every argument aside from value (which is the second argument, so you're stuck passing the first argument even though nothing uses it)
2. It doesn't actually use ctypes to achieve efficient storage/IPC communication (updating value involves pickling it, not just sending the raw data of a C array/struct)
3. It doesn't provide any of the interface of the other Value, so you can't use get_lock (or use a with statement to lock it, or manually call acquire or release) or get_obj.

I'm not sure what to do about it though; the manager version of Value is much more flexible, and I'm sure there is existing code that takes advantage of that, so we can't rewrite to make it ctypes backed. The multiprocessing.managers code is too new/complex for me to determine if any easy solution exists to expand multiprocessing.managers.ValueProxy to support context management/get_lock/get_obj to match the behavior of the class returned by multiprocessing.Value/multiprocessing.sharedctypes.Value, but it seems like, if we're going to let the docs imply a relationship, we ought to at least try to make the API of the two classes roughly match.

nosy: +josh.r

Python tracker <report at bugs.python.org>

More information about the docs mailing list