how can I execute a function string

Francis Avila francisgavila at yahoo.com
Mon Jan 12 21:23:20 EST 2004


Rajarshi Guha wrote in message ...
>Hi ,
> I have some code that generates a function on the fly in a string.
>At a later point in time I want to execute this function (which also
>requires a parameters to be passed to it). So the code is something like
>this:
>
>def generate_func():
> s = """ def function(x):
> print x
> return 2
>"""
> return s
>
>funcstring = generate_func()
>retval = ....
>
>That is, retval should have the value returned from the evaluation of the
>function in the string funcstring.
>
>Is this possible by means of simple function calls or does this involve
>some sort of black magic?
>
>Thanks,

What is it with code-generation this week?

Anyway, the exec statement (not function) will execute the contents of a
string or code object as though it were inline code:

E.g.:
>>> x
Traceback (most recent call last):
...
NameError: name 'x' is not defined
>>> exec 'x = 1'
>>> x
1
>>>

Use like so:

exec generate_func()
# 'function' is now in your namespace.
function('hello') # should print 'hello' and return 2.

A *slightly* better approach is to make a code object, using compile().

def gen_func():
    s = '''
    def f(x):
        return x
    '''
    return compile(s, '<source>', 'single')

exec gen_func() # f gets dumped into your namespace.

If you're very ambitious, you can generate an AST tree and compile that: see
the compile module.  In this simple case there's no advantage, however.

I'll have to think about how to turn the raw source of a function definition
into a callable.  I'm not sure it's possible in a 100% reliable manner.
Here's a first attempt (untested):

def makecallable(source):
    """Return a function from string source.

    'def <funcname>' must be the first tokens in source!

    """
    co = compile(source, '<makecallable()>', 'single')
    funcname = co.co_varnames[0] #This is VERY brittle!!
    fakelocals = {}
    exec co in globals(), fakelocals
    return fakelocals[funcname]

Now that I've told you about exec, I'll tell you that you almost certainly
shouldn't be using it.  There is most likely a better way to do what you're
doing than building code strings and executing them.  Python has a lot of
reflection, introspection, and dynamic object generation capabilities, which
generally remove the need for using exec, which is slow, hackish, and
error-prone.  Please tell us more about what you're doing.
--
Francis Avila




More information about the Python-list mailing list