2009-11-12 2 views
2

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

+0

Возможно, вам понадобится использовать декоратор, чтобы захватить имя функции ... но может быть и более простой способ, который я не знаю. – jldupont

ответ

11

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

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

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

+0

@Nadia Alramli [Попутно], Поздравляем за прохождение отметки в 10 000 повторений в скором времени! Я часто нахожу ваши ответы на этот вопрос и полезен (и, к сожалению, вы часто избивали меня ;-)) Следите за хорошей работой! – mjv

+0

@mjv, спасибо! Вы быстрее, что я точно: 8 079 в 2 месяца ничего себе! :) –

2

Быстрый пример для вас. Обратите внимание, что вы будете ожидать правильной семантики 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

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

Вы также можете воспользоваться возможностью eval() использовать любой объект сопоставления в качестве параметра locals. Вы можете создать объект сопоставления для поиска и компиляции объектов из своей базы данных по мере необходимости с помощью 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 

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

+0

Это более или менее то, что я планирую делать :) – exupero

Смежные вопросы