2

I have a database that holds the name of Python functions and a string for their code. I want the user to be able to enter a Python code and see the result. The problem is that I need to know the names of the functions they call in order to retrieve the code from the database. For instance, if they enter cubic_fit(1, 2, get_data()), I need a way to get the function names cubic_fit and get_data. Is there a good way to do this?

1
  • you might need to use a decorator in order to grab the function name... but there might be an easier way which I don't know. Commented Nov 12, 2009 at 23:57

3 Answers 3

11

The built-in function compile will do that for you exactly:

>>> compile("cubic_fit(1, 2, get_data())", '<string>', 'eval').co_names
('cubic_fit', 'get_data')

And it is safe to run. No code is actually being executed just compiled.

Sign up to request clarification or add additional context in comments.

2 Comments

@Nadia Alramli [In passing], Congrats for passing the 10k reps mark in speedy time! I often find your responses to the point and useful (and, unfortunately, you often beat me to it ;-) ) Keep up the good work!
@mjv, thanks! You are faster that me for sure: 8,079 in 2 month wow! :)
2

A quick example to you started. Note that you'll be expecting valid python semantics for this to work.

You can extend this to also parse your arguments...

import token, tokenize, StringIO

def extract_names(src):
    rawstr = StringIO.StringIO(unicode(src))
    tokens = tokenize.generate_tokens(rawstr.readline)
    for i, item in enumerate(tokens):
        toktype, toktext, (srow,scol), (erow,ecol), line = item
        if token.tok_name[toktype] == 'NAME':
            print 'name:', toktext

extract_names("cubic_fit(1, 2, get_data())")

# --> output:
# name: cubic_fit
# name: get_data

Comments

0

If you just want the names, then the compile() and co_names method will work best.

You also might take advantage of the capability of eval() to use any mapping object as its locals parameter. You could create a mapping object to look up and compile the objects from your database as needed by eval().

Example:

class LookitUp(object):
    def __init__(self):
        # simulate some data
        self.d = { "foo": "def foo(a):\n  return a + 2"}

    def __getitem__(self,key):
        localdict = {}
        c = compile(self.d.get(key,""),"<string>","exec")
        eval(c,globals(),localdict)
        return localdict[key]

d = LookitUp()

def bar(a): 
    return a - 1

print "foo from database :",eval("foo(3)",globals(), d)
print "bar from globals():",eval("bar(3)",globals(), d)
print "foo(bar(3))       :",eval("foo(bar(3))",globals(), d)

Result:

foo from database : 5
bar from globals(): 2
foo(bar(3))       : 4

You may need to modify based on what your source in the database looks like, but it's a place to start.

1 Comment

That's more or less what I'm planning to do :)

Your Answer

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.