Составление объектов и многопроцессорность Python

Если я реализую композицию объекта с помощью getattr и передам объект в новый процесс, я получу RecursionError из getattr. Вот пример:

from multiprocessing import Pool

class Bar:
    def __init__(self, bar):
        self.bar = bar

class Foo:
    def __init__(self, bar):
        self._bar = bar

    def __getattr__(self, attr):
        try:
            return getattr(self._bar, attr)
        except RecursionError:
            print('RecursionError while trying to access {}'.format(attr))
            raise AttributeError

def f(foo):
    print(foo.bar)

if __name__ == '__main__':
    foo = Foo(Bar('baz'))
    f(foo)
    p = Pool(1)
    p.map(f, [foo])

Выход такой:

baz
RecursionError while trying to access _bar
baz

Почему Foo не находит атрибут _bar и вынужден прибегать к getattr?

1 ответ

Проблема в том, что Python должен сериализовать foo возразить и воскресить его в новом процессе. __init__ не вызывается во время воскресения, поэтому ваш foo объект не будет иметь ._bar приписать достаточно рано.

Решение состоит в том, чтобы позволить сериализовать / воскрешать методы через специально, т.е. изменить свой __getattr__ чтобы:

def __getattr__(self, attr):
    if attr in {'__getstate__', '__setstate__'}:
        return object.__getattr__(self, attr)
    return getattr(self._bar, attr)

и это должно работать.

Другие вопросы по тегам