为什么在尝试使用 SharedMemoryManager (python 3.8) 替代 BaseManager 时会出现 NameError?

Why do we get a NameError when trying to use the SharedMemoryManager (python 3.8) as a replacement for the BaseManager?

Python 3.8 引入了新的共享内存功能。我们正在尝试使用 SharedMemoryManager 并抛出 NameError

我认为我们在复杂的场景中可能会做错什么,所以我使用 python 文档片段对其进行了分解。

try:
    # python >= 3.8
    from multiprocessing.managers import SharedMemoryManager as Manager
except:
    # python < 3.8
    from multiprocessing.managers import BaseManager as Manager

class MathsClass:
    def add(self, x, y):
        return x + y
    def mul(self, x, y):
        return x * y

class MyManager(Manager):
    pass

MyManager.register('Maths', MathsClass)

if __name__ == '__main__':
    with MyManager() as manager:
        maths = manager.Maths()
        print(maths.add(4, 3))         # prints 7
        print(maths.mul(7, 8))         # prints 56

这几乎取自多处理文档(后备导入除外)并且在 python 3.7 中工作正常但在 python 3.8 中抛出以下错误:

Traceback (most recent call last):
  File "scripts/debug_shared_memory_issue.py", line 21, in <module>
    maths = manager.Maths()
  File "/usr/lib/python3.8/multiprocessing/managers.py", line 740, in temp
    token, exp = self._create(typeid, *args, **kwds)
  File "/usr/lib/python3.8/multiprocessing/managers.py", line 625, in _create
    id, exposed = dispatch(conn, None, 'create', (typeid,)+args, kwds)
  File "/usr/lib/python3.8/multiprocessing/managers.py", line 91, in dispatch
    raise convert_to_error(kind, result)
multiprocessing.managers.RemoteError: 
---------------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3.8/multiprocessing/managers.py", line 210, in handle_request
    result = func(c, *args, **kwds)
  File "/usr/lib/python3.8/multiprocessing/managers.py", line 1312, in create
    if hasattr(self.registry[typeid][-1], "_shared_memory_proxy"):
NameError: name 'self' is not defined
---------------------------------------------------------------------------

python 3.8 的发行说明和文档说 SharedMemoryManager 是 "A subclass of BaseManager",因此我们希望它可以作为直接替代品。但似乎并非如此。我们做错了什么?查看当前 CPython 的 3.8 分支,似乎没有对此进行相关更改。在 Python 3.9 中,create 函数中有一个明确的 self arg。但是 3.9 是 WIP,所以我们宁愿不在生产软件中使用它。

感谢您的帮助!

这是 python/cpython@142566c (v3.9.0a1) 中修复的错误。

您可以从 python/cpython/blob/v3.9.0a1/Lib/multiprocessing/managers.py#L1269-L1277:

打补丁
from multiprocessing.managers import SharedMemoryManager as Manager

import sys

if sys.version_info < (3, 9):
    from multiprocessing.managers import Server, SharedMemoryServer

    def create(self, c, typeid, /, *args, **kwargs):
        if hasattr(self.registry[typeid][-1], "_shared_memory_proxy"):
            kwargs['shared_memory_context'] = self.shared_memory_context
        return Server.create(self, c, typeid, *args, **kwargs)

    SharedMemoryServer.create = create