Получить функции, вызываемые в выражении Python - PullRequest
2 голосов
/ 13 ноября 2009

У меня есть база данных, которая содержит имена функций Python и строку для их кода. Я хочу, чтобы пользователь мог вводить код Python и видеть результат. Проблема в том, что мне нужно знать имена функций, которые они вызывают, чтобы получить код из базы данных. Например, если они вводят cubic_fit(1, 2, get_data()), мне нужен способ получить имена функций cubic_fit и get_data. Есть ли хороший способ сделать это?

Ответы [ 3 ]

11 голосов
/ 13 ноября 2009

Встроенная функция compile сделает это именно для вас:

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

И безопасно бежать. На самом деле никакой код не выполняется, только что скомпилированный.

2 голосов
/ 13 ноября 2009

Быстрый пример для вас начался. Обратите внимание, что вы ожидаете допустимой семантики Python для этого.

Вы можете расширить это, чтобы также проанализировать ваши аргументы ...

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
0 голосов
/ 13 ноября 2009

Если вам нужны только имена, тогда метод compile () и co_names будут работать лучше всего.

Вы также можете воспользоваться возможностью eval () использовать любой объект отображения в качестве параметра localals. Вы можете создать объект сопоставления для поиска и компиляции объектов из вашей базы данных, как это требуется eval ().

Пример:

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)

Результат:

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

Возможно, вам придется изменить в зависимости от того, как выглядит ваш источник в базе данных, но это место для начала.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...