Reputation: 21
If I implement object composition with getattr and pass the object into a new process, I get an RecursionError from getattr. Here is an example:
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])
The output is this:
baz
RecursionError while trying to access _bar
baz
Why doesn't Foo find the _bar attribute and has to resort to getattr?
Upvotes: 2
Views: 217
Reputation: 27321
The problem is that Python needs to serialize the foo
object and resurrect it in the new process. __init__
isn't called during resurrection, so your foo
object won't have a ._bar
attribute early enough.
The solution is to let the serialize/resurrect methods through specially, ie. change your __getattr__
to:
def __getattr__(self, attr):
if attr in {'__getstate__', '__setstate__'}:
return object.__getattr__(self, attr)
return getattr(self._bar, attr)
and it should work.
Upvotes: 3