-
-
Notifications
You must be signed in to change notification settings - Fork 189
Closed
Labels
Milestone
Description
Consider the following:
def outer():
def inner():
inner
return innerAttempting to dump the inner function (dill.dumps(outer())) results in RecursionError: maximum recursion depth exceeded while calling a Python object. Note, that the third line in the example is not a call to inner, but just a reference.
Python 3.9.1
dill 0.3.3
Stacktrace
/usr/lib/python3.9/site-packages/dill/_dill.py in dumps(obj, protocol, byref, fmode, recurse, **kwds)
271 """pickle an object to a string"""
272 file = StringIO()
--> 273 dump(obj, file, protocol, byref, fmode, recurse, **kwds)#, strictio)
274 return file.getvalue()
275
/usr/lib/python3.9/site-packages/dill/_dill.py in dump(obj, file, protocol, byref, fmode, recurse, **kwds)
265 _kwds = kwds.copy()
266 _kwds.update(dict(byref=byref, fmode=fmode, recurse=recurse))
--> 267 Pickler(file, protocol, **_kwds).dump(obj)
268 return
269
/usr/lib/python3.9/site-packages/dill/_dill.py in dump(self, obj)
452 raise PicklingError(msg)
453 else:
--> 454 StockPickler.dump(self, obj)
455 stack.clear() # clear record of 'recursion-sensitive' pickled objects
456 return
/usr/lib/python3.9/pickle.py in dump(self, obj)
485 if self.proto >= 4:
486 self.framer.start_framing()
--> 487 self.save(obj)
488 self.write(STOP)
489 self.framer.end_framing()
/usr/lib/python3.9/pickle.py in save(self, obj, save_persistent_id)
558 f = self.dispatch.get(t)
559 if f is not None:
--> 560 f(self, obj) # Call unbound method with explicit self
561 return
562
/usr/lib/python3.9/site-packages/dill/_dill.py in save_function(pickler, obj)
1442 if _memo: pickler._recurse = False
1443 fkwdefaults = getattr(obj, '__kwdefaults__', None)
-> 1444 pickler.save_reduce(_create_function, (obj.__code__,
1445 globs, obj.__name__,
1446 obj.__defaults__, obj.__closure__,
/usr/lib/python3.9/pickle.py in save_reduce(self, func, args, state, listitems, dictitems, state_setter, obj)
690 else:
691 save(func)
--> 692 save(args)
693 write(REDUCE)
694
/usr/lib/python3.9/pickle.py in save(self, obj, save_persistent_id)
558 f = self.dispatch.get(t)
559 if f is not None:
--> 560 f(self, obj) # Call unbound method with explicit self
561 return
562
/usr/lib/python3.9/pickle.py in save_tuple(self, obj)
899 write(MARK)
900 for element in obj:
--> 901 save(element)
902
903 if id(obj) in memo:
/usr/lib/python3.9/pickle.py in save(self, obj, save_persistent_id)
558 f = self.dispatch.get(t)
559 if f is not None:
--> 560 f(self, obj) # Call unbound method with explicit self
561 return
562
/usr/lib/python3.9/pickle.py in save_tuple(self, obj)
884 if n <= 3 and self.proto >= 2:
885 for element in obj:
--> 886 save(element)
887 # Subtle. Same as in the big comment below.
888 if id(obj) in memo:
/usr/lib/python3.9/pickle.py in save(self, obj, save_persistent_id)
558 f = self.dispatch.get(t)
559 if f is not None:
--> 560 f(self, obj) # Call unbound method with explicit self
561 return
562
/usr/lib/python3.9/site-packages/dill/_dill.py in save_cell(pickler, obj)
1176 log.info("Ce: %s" % obj)
1177 f = obj.cell_contents
-> 1178 pickler.save_reduce(_create_cell, (f,), obj=obj)
1179 log.info("# Ce")
1180 return
/usr/lib/python3.9/pickle.py in save_reduce(self, func, args, state, listitems, dictitems, state_setter, obj)
690 else:
691 save(func)
--> 692 save(args)
693 write(REDUCE)
694
/usr/lib/python3.9/pickle.py in save(self, obj, save_persistent_id)
558 f = self.dispatch.get(t)
559 if f is not None:
--> 560 f(self, obj) # Call unbound method with explicit self
561 return
562
/usr/lib/python3.9/pickle.py in save_tuple(self, obj)
884 if n <= 3 and self.proto >= 2:
885 for element in obj:
--> 886 save(element)
887 # Subtle. Same as in the big comment below.
888 if id(obj) in memo:
... last 12 frames repeated, from the frame below ...
/usr/lib/python3.9/pickle.py in save(self, obj, save_persistent_id)
558 f = self.dispatch.get(t)
559 if f is not None:
--> 560 f(self, obj) # Call unbound method with explicit self
561 return
562
RecursionError: maximum recursion depth exceeded while calling a Python objectA few variations/use-cases for this kind of self-referencing:
def make_function_with_self_recursion(a=0, b=1):
def fib(n):
if n == 0:
return a
if n == 1:
return b
return fib(n-1) + fib(n-2)
return fib
def make_function_with_state():
def _fun():
_fun.state += 1
return _fun.state
_fun.state = 0
return _funReactions are currently unavailable