Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Yes! I got it (at least I think) -- that is, the more generic problem of pickling a function. Python is so wonderful :), I found out most of it though the dir() function and a couple of web searches. Also wonderful to have it [hopefully] solved, I needed it also.</p> <p>I haven't done a lot of testing on how robust this co_code thing is (nested fcns, etc.), and it would be nice if someone could look up how to hook Python so functions can be pickled automatically (e.g. they might sometimes be closure args).</p> <p>Cython module _pickle_fcn.pyx</p> <pre><code># -*- coding: utf-8 -*- cdef extern from "Python.h": object PyCell_New(object value) def recreate_cell(value): return PyCell_New(value) </code></pre> <p>Python file</p> <pre><code>#!/usr/bin/env python # -*- coding: utf-8 -*- # author gatoatigrado [ntung.com] import cPickle, marshal, types import pyximport; pyximport.install() import _pickle_fcn def foo(bar, baz) : def closure(waldo) : return baz * waldo return closure # really this problem is more about pickling arbitrary functions # thanks so much to the original question poster for mentioning marshal # I probably wouldn't have found out how to serialize func_code without it. fcn_instance = foo("unused?", -1) code_str = marshal.dumps(fcn_instance.func_code) name = fcn_instance.func_name defaults = fcn_instance.func_defaults closure_values = [v.cell_contents for v in fcn_instance.func_closure] serialized = cPickle.dumps((code_str, name, defaults, closure_values), protocol=cPickle.HIGHEST_PROTOCOL) code_str_, name_, defaults_, closure_values_ = cPickle.loads(serialized) code_ = marshal.loads(code_str_) closure_ = tuple([_pickle_fcn.recreate_cell(v) for v in closure_values_]) # reconstructing the globals is like pickling everything :) # for most functions, it's likely not necessary # it probably wouldn't be too much work to detect if fcn_instance global element is of type # module, and handle that in some custom way # (have the reconstruction reinstantiate the module) reconstructed = types.FunctionType(code_, globals(), name_, defaults_, closure_) print(reconstructed(3)) </code></pre> <p>cheers, <br /> Nicholas</p> <p><strong>EDIT</strong> - more robust global handling is necessary for real-world cases. fcn.func_code.co_names lists global names.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload