[IPython-user] can't pickle interactively defined function

Robert Kern robert.kern@gmail....
Mon Oct 27 12:19:45 CDT 2008


Robin wrote:
> Hi,
> 
> After having some trouble with the processing module in ipython I
> think the problem is related to functions defined interactively in
> ipython (or through an %edit) being unpickle-able. Since this has
> nothing to do really with the processing module I thought I'd start a
> new thread. The simplest way to demonstrate the problem is below:
> 
> In [1]: from pooltest import f
> In [2]: f??
> Type:           function
> Base Class:     <type 'function'>
> String Form:    <function f at 0x2532370>
> Namespace:      Interactive
> File:           /Users/robince/bzr/handy/pooltest.py
> Definition:     f(x)
> Source:
> def f(x):
>     return x*x
> In [3]: from cPickle import dumps
> In [4]: dumps(f)
> Out[4]: 'cpooltest\nf\np1\n.'
> In [5]: def f(x):
>    ...:     return x*x
>    ...:
> In [6]: f??
> Type:           function
> Base Class:     <type 'function'>
> String Form:    <function f at 0x25323b0>
> Namespace:      Interactive
> File:           /Users/robince/bzr/handy/<ipython console>
> Definition:     f(x)
> Docstring [source file open failed]:
>     <no docstring>
> 
> In [7]: dumps(f)
> ---------------------------------------------------------------------------
> TypeError                                 Traceback (most recent call last)
> 
> /Users/robince/bzr/handy/<ipython console> in <module>()
> 
> /Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/copy_reg.pyc
> in _reduce_ex(self, proto)
>      67     else:
>      68         if base is self.__class__:
> ---> 69             raise TypeError, "can't pickle %s objects" % base.__name__
>      70         state = base(self)
>      71     args = (self.__class__, base, state)
> 
> TypeError: can't pickle function objects
> 
> Is this a bug?

It's certainly undesirable. BTW, to replicate the exact code path from 
multiprocessing, use dumps(f, 2). Using the pure Python pickle module helped me 
track it down a bit more:

In [17]: pickle.dumps(f, 2)
---------------------------------------------------------------------------
PicklingError                             Traceback (most recent call last)

/Users/rkern/today/<ipython console> in <module>()

/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.pyc in 
dumps(obj, protocol)
    1364 def dumps(obj, protocol=None):
    1365     file = StringIO()
-> 1366     Pickler(file, protocol).dump(obj)
    1367     return file.getvalue()
    1368

/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.pyc in 
dump(self, obj)
     222         if self.proto >= 2:
     223             self.write(PROTO + chr(self.proto))
--> 224         self.save(obj)
     225         self.write(STOP)
     226

/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.pyc in 
save(self, obj)
     284         f = self.dispatch.get(t)
     285         if f:
--> 286             f(self, obj) # Call unbound method with explicit self
     287             return
     288

/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.pyc in 
save_global(self, obj, name, pack)
     746             raise PicklingError(
     747                 "Can't pickle %r: it's not found as %s.%s" %
--> 748                 (obj, module, name))
     749         else:
     750             if klass is not obj:

PicklingError: Can't pickle <function f at 0xaeb9f0>: it's not found as __main__.f

In [18]: import __main__

In [19]: __main__.
__main__.__IP              __main__.__getattribute__  __main__.__reduce__
__main__.__builtins__      __main__.__hash__          __main__.__reduce_ex__
__main__.__class__         __main__.__init__          __main__.__repr__
__main__.__delattr__       __main__.__module__        __main__.__setattr__
__main__.__dict__          __main__.__name__          __main__.__str__
__main__.__doc__           __main__.__new__           __main__.__weakref__
__main__.__file__          __main__.__nonzero__


We're not putting things defined in the namespace in the __main__ module. I'm 
not sure what the best approach should be, here. There might be multiple 
namespaces floating around. Presumably, they shouldn't all be linked to __main__.

-- 
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
  that is made terrible by our own mad attempt to interpret it as though it had
  an underlying truth."
   -- Umberto Eco



More information about the IPython-user mailing list