在 运行 时间跨多进程更新字典时出现问题

Issues updating dictionary at run-time across multiprocesses

我正在尝试使用 pygame 配置一些可以在运行时动态 changed/updated 的键绑定。您可以在下面看到我的第一个原型尝试。我收到一条令人困惑的错误消息,我被卡住了。它在初始化期间抱怨 multiprocessing/connection.py 无法访问 test.py 中的 'Pitch'。

Traceback (most recent call last):
  File "/opt/pycharm-community-2017.2.3/helpers/pydev/pydevd.py", line 1599, in <module>
    globals = debugger.run(setup['file'], None, None, is_module)
  File "/opt/pycharm-community-2017.2.3/helpers/pydev/pydevd.py", line 1026, in run
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "/opt/pycharm-community-2017.2.3/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "/home/jesse/code/pygame_controller/test.py", line 56, in <module>
    test_rpyc()
  File "/home/jesse/code/pygame_controller/test.py", line 42, in test_rpyc
    i = InputProcess(mapping)
  File "/home/jesse/code/pygame_controller/input_rpc.py", line 111, in __init__
    i = Input(mapping)
  File "/home/jesse/code/pygame_controller/input_rpc.py", line 58, in __init__
    set_mapping(mapping)
  File "/home/jesse/code/pygame_controller/input_rpc.py", line 52, in set_mapping
    _mapping.update(mapping)
  File "<string>", line 2, in update
  File "/usr/lib64/python3.5/multiprocessing/managers.py", line 732, in _callmethod
    raise convert_to_error(kind, result)
multiprocessing.managers.RemoteError: 
---------------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib64/python3.5/multiprocessing/managers.py", line 228, in serve_client
    request = recv()
  File "/usr/lib64/python3.5/multiprocessing/connection.py", line 251, in recv
    return ForkingPickler.loads(buf.getbuffer())
AttributeError: Can't get attribute 'Pitch' on <module '__main__' from '/home/jesse/code/pygame_controller/test.py'>
---------------------------------------------------------------------------

当我调试时,在 connection.py 中,我可以查看整个映射字典。看起来 connection.py 有 dict 对象,这就是为什么我很困惑为什么它最后会抛出错误。多进程模块是否无法访问 namedtuple 'Pitch'?我可以将 'Pitch' namedtuples 更改为整数,然后这段代码就可以正常工作了。有没有更好的方法来更新映射,可能使用 rpyc?如果我不能在这里取得进展,Rpyc 就是我接下来要制作的原型。

test.py

from collections import namedtuple
from input import event_queue, InputProcess

Pitch = namedtuple('Pitch', 'value')

mapping = {
    'keyboard': {
        'w': {  # key
            'key_down': Pitch(-1.0),  # event
            'key_up': Pitch(0.0),  # event
        },
    },
}


def test():
    i = InputProcess(mapping)
    i.start()

    while True:
        event = event_queue.get()
        print(event)


if __name__ == '__main__':
    test()

input.py

import pygame
from multiprocessing import Manager, Process

_manager = Manager()
_mapping = _manager.dict()

event_queue = _manager.Queue()


def initialize(joystick=True):
    """Initialize pygame & joystick"""
    ...


def set_mapping(mapping):
    """Change the current keyboard/joystick mappings"""
    global _mapping

    for k, _ in _mapping.items():
        _mapping.pop(k)

    _mapping.update(mapping)


class Input(object):
    def __init__(self, mapping=None):
        if mapping is not None:
            set_mapping(mapping)

    @staticmethod
    def run():    
        while True:
            event = pygame.event.wait()

            # handle event


class InputProcess(object):
    def __init__(self, mapping=None):
        initialize()
        i = Input(mapping)

        self.process = Process(target=i.run)

    def start(self):
        self.process.start()

    def stop(self):
        self.process.terminate()
        self.process.join()

这是关键。

AttributeError: Can't get attribute 'Pitch' on <module '__main__' from '/home/jesse/code/pygame_controller/test.py'>

test.py 是 运行ning 为 __main__。如果您创建一个新文件导入您需要的内容并从那里导入 运行,那么它将能够在 test.py.

中访问 Pitch

示例:

example.py

from .test import test

if __name__ == '__main__':
    test()