I have read in a number of threads that Python pickle
/cPickle
cannot pickle lambda functions. However the following code works, using Python 2.7.6:
import cPickle as pickle
if __name__ == "__main__":
s = pickle.dumps(lambda x, y: x+y)
f = pickle.loads(s)
assert f(3,4) == 7
So what is going on? Or, rather, what is the limit of pickling lambdas?
[EDIT] I think i know why this code runs. I forgot (sorry!) i am running stackless python, which has a form of micro-threads called tasklets executing a function. These tasklets can be halted, pickled, unpickled and continued, so i guess (asked on the stackless mailing list) that it also provides a way to pickle function bodies.
Yes, python can pickle lambda functions… but only if you have something that uses
copy_reg
to register how to pickle lambda functions -- the packagedill
loads thecopy_reg
you need into the pickle registry for you, when youimport dill
.get dill here: https://github.com/uqfoundation
No, Python can't pickle lambda functions:
Not sure what you did that succeeded...
Python can pickle lambdas. We will cover Python 2 and 3 separately as implementation of pickle are different in different Python versions.
pickle
uses pickle registry which is nothing but a mapping fromtype
to the function to use for serializing (pickling) objects of that type. You can see pickle registry as:To pickle custom types, Python provides
copy_reg
module to register our functions. You can read more about it here. By default,copy_reg
module supports pickling of the following additional types:Now, type of
lambda
functions istypes.FunctionType
. However, the builtin function for this typefunction: <function pickle.save_global>
is not able to serialize lambda functions. Therefore, all third party libraries likedill
,cloudpickle
, etc override the inbuilt method to serialize lambda functions with some additional logic. Let's importdill
and see what it does.Now, let's try to pickle lambda function.
It WORKS!!
In Python 2 we have two versions of
pickle
-Now, let's try to pickle lambda with C implementation
cPickle
.What went wrong? Let's see the dispatch table of
cPickle
.The implementation of
pickle
andcPickle
is different.Importing
dill makes only Python version ofpickle
work. The disadvantage of usingpickle
instead ofcPickle
is that it can be as much as 1000 times slower than cPickle.In Python 3, there is no module named
cPickle
. We havepickle
instead which also doesn't support pickling oflambda
functions by default. Let's see it's dispatch table:Wait. I tried looking up dispatch_table of
pickle
not_pickle
._pickle
is the alternative and faster C implementation of pickle. But we haven't imported it yet! This C implementation is imported automatically, if it is available, at the end of pure Pythonpickle
module.We are still left with the question of pickling lambdas in Python 3. The answer is you CAN'T with the native
pickle
or_pickle
. You will need to importdill
or cloudpickle and use that instead of the native pickle module.I hope this clears all the doubts.