As a follow up to this question:
Is there an easy way to pickle a python function (or otherwise serialize its code)?
I would like to see an example of this bullet from the above post:
"If the function references globals (including imported modules, other functions etc) that you need to pick up, you'll need to serialise these too, or recreate them on the remote side. My example just gives it the remote process's global namespace."
I have a simple test going where I am writing a functions byte code to a file using marshal:
def g(self,blah):
print blah
def f(self):
for i in range(1,5):
print 'some function f'
g('some string used by g')
data = marshal.dumps(f.func_code)
file = open('/tmp/f2.txt', 'w')
file.write(data)
Then starting a fresh python instance I do:
file = open('/tmp/f2.txt', 'r')
code = marshal.loads(file.read())
func2 = types.FunctionType(code, globals(), "some_func_name");
func2('blah')
This results in a:
NameError: global name 'g' is not defined
This is independent of the different approaches I have made to including g. I have tried basically the same approach to sending g over as f but f can still not see g. How do I get g into the global namespace so that it can be used by f in the receiving process?
Someone also recommended looking at pyro as an example of how to do this. I have already made an attempt at trying to understand the related code in the disco project. I took their dPickle class and tried to recreate their disco/tests/test_pickle.py functionality in a standalone app without success. My experiment had problems doing the function marshaling with the dumps call. Anyway, maybe a pyro exploration is next.
In summary, the basic functionality I am after is being able to send a method over the wire and have all the basic "workspace" methods sent over with it (like g).
Example with changes from answer:
Working function_writer:
import marshal, types
def g(blah):
print blah
def f():
for i in range(1,5):
print 'some function f'
g('blah string used by g')
f_data = marshal.dumps(f.func_code)
g_data = marshal.dumps(g.func_code);
f_file = open('/tmp/f.txt', 'w')
f_file.write(f_data)
g_file = open('/tmp/g.txt', 'w')
g_file.write(g_data)
Working function_reader:
import marshal, types
f_file = open('/tmp/f.txt', 'r')
g_file = open('/tmp/g.txt', 'r')
f_code = marshal.loads(f_file.read())
g_code = marshal.loads(g_file.read())
f = types.FunctionType(f_code, globals(), 'f');
g = types.FunctionType(g_code, globals(), 'g');
f()
See Question&Answers more detail:
os