Составление объектов и многопроцессорность 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)
и это должно работать.