Search code examples
pythonjupyter-notebookpickledill

Find problematic variable when writing to pickle


I'm trying to save a Jupiter notebook session using dill. But I get the 'NoneType' object is not callable. I have no idea what object is causing this problem. So does anyone have any ideas to debug and find this variable?

Here is the traceback:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-140-c41ad0030e13> in <module>()
      1 import dill
----> 2 dill.dump_session('notebook_env.dill')

~/hands-on/lib/python3.5/site-packages/dill/dill.py in dump_session(filename, main, byref)
    370         pickler._recurse = False # disable pickling recursion for globals
    371         pickler._session = True  # is best indicator of when pickling a session
--> 372         pickler.dump(main)
    373     finally:
    374         f.close()

~/hands-on/lib/python3.5/pickle.py in dump(self, obj)
    406         if self.proto >= 4:
    407             self.framer.start_framing()
--> 408         self.save(obj)
    409         self.write(STOP)
    410         self.framer.end_framing()

~/hands-on/lib/python3.5/pickle.py in save(self, obj, save_persistent_id)
    473         f = self.dispatch.get(t)
    474         if f is not None:
--> 475             f(self, obj) # Call unbound method with explicit self
    476             return
    477 

~/hands-on/lib/python3.5/site-packages/dill/dill.py in save_module(pickler, obj)
   1236                 + ["__builtins__", "__loader__"]]
   1237             pickler.save_reduce(_import_module, (obj.__name__,), obj=obj,
-> 1238                                 state=_main_dict)
   1239             log.info("# M1")
   1240         else:

~/hands-on/lib/python3.5/pickle.py in save_reduce(self, func, args, state, listitems, dictitems, obj)
    625 
    626         if state is not None:
--> 627             save(state)
    628             write(BUILD)
    629 

~/hands-on/lib/python3.5/pickle.py in save(self, obj, save_persistent_id)
    473         f = self.dispatch.get(t)
    474         if f is not None:
--> 475             f(self, obj) # Call unbound method with explicit self
    476             return
    477 

~/hands-on/lib/python3.5/site-packages/dill/dill.py in save_module_dict(pickler, obj)
    869             # we only care about session the first pass thru
    870             pickler._session = False
--> 871         StockPickler.save_dict(pickler, obj)
    872         log.info("# D2")
    873     return

~/hands-on/lib/python3.5/pickle.py in save_dict(self, obj)
    812 
    813         self.memoize(obj)
--> 814         self._batch_setitems(obj.items())
    815 
    816     dispatch[dict] = save_dict

~/hands-on/lib/python3.5/pickle.py in _batch_setitems(self, items)
    838                 for k, v in tmp:
    839                     save(k)
--> 840                     save(v)
    841                 write(SETITEMS)
    842             elif n:

~/hands-on/lib/python3.5/pickle.py in save(self, obj, save_persistent_id)
    493             reduce = getattr(obj, "__reduce_ex__", None)
    494             if reduce is not None:
--> 495                 rv = reduce(self.proto)
    496             else:
    497                 reduce = getattr(obj, "__reduce__", None)

TypeError: 'NoneType' object is not callable

Solution

  • I'm the dill author. Try the methods in dill.detect -- probably the easiest is to try dill.detect.trace(True). Trace will print the object-by-object recursive approach dill takes when it attempts to serialize something.

    >>> x = [lambda x:x, min, 4]
    >>> import dill
    >>> dill.detect.trace(True)
    >>> dill.dumps(x)
    F1: <function <lambda> at 0x105a99758>
    F2: <function _create_function at 0x105efac80>
    # F2
    Co: <code object <lambda> at 0x105a3e6b0, file "<stdin>", line 1>
    T1: <type 'code'>
    F2: <function _load_type at 0x105efab90>
    # F2
    # T1
    # Co
    D1: <dict object at 0x105985168>
    # D1
    D2: <dict object at 0x105fd9a28>
    # D2
    # F1
    B2: <built-in function min>
    # B2
    '\x80\x02]q\x00(cdill.dill\n_create_function\nq\x01(cdill.dill\n_load_type\nq\x02U\x08CodeTypeq\x03\x85q\x04Rq\x05(K\x01K\x01K\x01KCU\x04|\x00\x00Sq\x06N\x85q\x07)U\x01xq\x08\x85q\tU\x07<stdin>q\nU\x08<lambda>q\x0bK\x01U\x00q\x0c))tq\rRq\x0ec__builtin__\n__main__\nh\x0bNN}q\x0ftq\x10Rq\x11c__builtin__\nmin\nq\x12K\x04e.'
    >>>