1

¡Hi everybody!

What I have to do is this:

import pickle
exec "def f(): print 'Hi!'"
code = pickle.dumps(f)
print code

As you can see, it works fine.

But, in order to avoid defining global variables, (as for example f in previous code), I'd like to do something like this:

import pickle
d = {}
exec "def f(): print 'Hi!'" in d
d['f']()
code = pickle.dumps(d['f'])
print code

It prints 'Hi!', it means that python recognizes d['f'] as a function, but it can't pickle it.

Do you have any idea of how to do this? I think that it is because in the former case, python knew where to find the function (it is in '__main__') but in the latter case, it's inside a dictionary located in '__main__' I think that if you can tell python the real module direction of this function, it will work.

Thanks!

asked Jul 2, 2015 at 18:24
4
  • 2
    "In order to avoid defining global variables..." If you're hesitant to even define functions in the global scope, you may be taking that advice a bit too far. Anyway, d is global, so you're not really gaining much here. Commented Jul 2, 2015 at 18:34
  • What I mean is that I don't like that when I use the command exec(), it defines global variables (for example, I did'nt define f in the program. It was defined after using exec). That's why I have to keep all those variables in a dict. It's done by using exec code in dict Commented Jul 2, 2015 at 18:38
  • I suggest not using exec at all. Just write your def f(): regularly. Commented Jul 2, 2015 at 18:39
  • But in practice, the string will be replaced by any python code, and I don't know what it is, that's why I need to use exec. Commented Jul 2, 2015 at 18:48

2 Answers 2

2

pickle pickles functions by name. Rather than attempting to dump and restore the bytecode, it just says "okay, this function is __main__.f, so to unpickle it, look in the __main__ module and retrieve the thing called f". This is pretty much necessary; if you unpickle a function f in an interpreter environment where f doesn't exist or does something different, then to preserve the original behavior of the unpickled function, you'd need to somehow retain all the functions it references, all the modules it uses, all the global variables that don't exist any more, etc. You'd need to make sure that recursive references to f inside f use the unpickled function instead of the new interpreter's f, and it all becomes a horrible mess.

The point of that all is that pickled functions have to be global. If you look in the module specified by their __module__ and look for the thing named by their __name__, you have to find the function, or you can't unpickle it. Thus, you can't exec the function definition in a fake global dictionary, and exec-ing definitions of functions you want to pickle at all is a highly bug-prone maneuver.

answered Jul 2, 2015 at 18:53
Sign up to request clarification or add additional context in comments.

Comments

1

I've found a very nice solution here: Dynamically importing Python module

And a code to solve the above problem is this:

import pickle
import sys
import imp
foo = imp.new_module("foo")
sys.modules["foo"] = foo
exec "def f(): print 'Hi!'" in foo.__dict__
code = pickle.dumps(foo.f)
print code

As you can see, the solution is to construct a new module and the function will be pickleable

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.