Как выполнить строку, содержащую код Python в Python?
Как выполнить строку, содержащую код Python в Python?
12 ответов
для утверждения, используйте exec(string) (в Python 2/3) или exec string (Python 2):
>>> mycode = 'print "hello world"'
>>> exec(mycode)
Hello world
когда вам нужно значение выражения, использовать eval(string):
>>> x = eval("2+2")
>>> x
4
однако первым шагом должно быть спросить себя, действительно ли вам это нужно. Выполнение кода обычно должно быть последним средством: он медленный, уродливый и опасный, если он может содержать введенный пользователем код. Вы всегда должны смотреть на альтернативы в первую очередь, такие как функции более высокого порядка, чтобы увидеть, могут ли они лучше удовлетворить ваши потребности.
в примере строка выполняется как код с помощью функции exec.
import sys
import StringIO
# create file-like string to capture output
codeOut = StringIO.StringIO()
codeErr = StringIO.StringIO()
code = """
def f(x):
x = x + 1
return x
print 'This is my output.'
"""
# capture output and errors
sys.stdout = codeOut
sys.stderr = codeErr
exec code
# restore stdout and stderr
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__
print f(4)
s = codeErr.getvalue()
print "error:\n%s\n" % s
s = codeOut.getvalue()
print "output:\n%s" % s
codeOut.close()
codeErr.close()
помните, что из версии 3 exec - Это функция!
поэтому всегда используйте exec(mystring) вместо exec mystring.
eval и exec являются правильным решением, и их можно использовать в безопасное порядке.
как говорится в справочное руководство Python и ясно объяснено в этой руководства eval и exec функции принимают два дополнительных параметра, которые позволяют пользователю указать, какие глобальные и локальные функции и переменные доступны.
например:
public_variable = 10
private_variable = 2
def public_function():
return "public information"
def private_function():
return "super sensitive information"
# make a list of safe functions
safe_list = ['public_variable', 'public_function']
safe_dict = dict([ (k, locals().get(k, None)) for k in safe_list ])
# add any needed builtins back in
safe_dict['len'] = len
>>> eval("public_variable+2", {"__builtins__" : None }, safe_dict)
12
>>> eval("private_variable+2", {"__builtins__" : None }, safe_dict)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name 'private_variable' is not defined
>>> exec("print \"'%s' has %i characters\" % (public_function(), len(public_function()))", {"__builtins__" : None}, safe_dict)
'public information' has 18 characters
>>> exec("print \"'%s' has %i characters\" % (private_function(), len(private_function()))", {"__builtins__" : None}, safe_dict)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name 'private_function' is not defined
по существу вы определяете пространство имен, в котором будет выполняться код.
eval() только для выражений, в то время как eval('x+1') работает, eval('x=1') не будет работать, например. В этом случае лучше использовать exec, или даже лучше: попробуйте найти лучшее решение:)
вы выполняете код с помощью exec, как и в следующем сеансе ожидания:
>>> kw = {}
>>> exec( "ret = 4" ) in kw
>>> kw['ret']
4
избежать exec и eval
используя exec и eval в Python очень неодобрительно.
есть лучшие альтернативы
из верхнего ответа (акцент мой):
для утверждения, используйте
exec.когда вам нужно значение выражения, использовать
eval.однако первым шагом должно быть спросить себя, действительно ли вам это нужно. выполнение кода должно как правило, позиция последней инстанции: это медленно, уродливо и опасно, если он может содержать введенный пользователем код. Вы всегда должны смотреть на альтернативы во-первых, такие как функции высшего порядка, чтобы увидеть, если они могут лучше удовлетворить ваши потребности.
установить и получить значения переменных с именами в строках
[while
eval] будет работать, как правило, нет рекомендуется использовать имена переменных, имеющие значение для самой программы.вместо этого лучше использовать dict.
это не идиоматические
от http://lucumr.pocoo.org/2011/2/1/exec-in-python/ (Курсив мой)
Python не PHP
не пытайтесь обойти идиомы Python, потому что некоторые другие языки делают это по-другому. Пространства имен в Python и просто потому что это дает вам инструмент
execЭто не означает, что вы должны использовать этот инструмент.
опасно
от http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html (Курсив мой)
таким образом, eval не является безопасным, даже если вы удалите все глобалы и встроенные!
проблема со всеми этими попытки защитить eval () заключается в том, что они являются черными списками. Они явно удалите вещи, которые могут быть опасными. Это проигранная битва, потому что если в списке остался только один элемент, вы можете атаковать систему.
Итак, можно ли сделать eval безопасным? Трудно сказать. На данный момент я думаю, что вы не можете причинить никакого вреда, если не можете использовать двойные подчеркивания, поэтому, возможно, если вы исключите любую строку с двойными подчеркиваниями, вы в безопасности. Возможно...
трудно читать и пойми!--14-->
от http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (Курсив мой):
во-первых,
execзатрудняет людям чтение вашего кода. Чтобы понять, что происходит, мне не просто нужно прочитать ваш код,я должен прочитать ваш код, выяснить, какую строку он собирается генерировать, а затем прочитать этот виртуальный код. Итак, если вы работаете в команде, или публикация программного обеспечения с открытым исходным кодом или обращение за помощью к кому-то вроде StackOverflow затрудняют помощь других людей. И если есть шанс, что вы собираетесь отлаживать или расширять этот код через 6 месяцев, вы усложняете его для себя напрямую.
Ok .. Я знаю,что это не совсем ответ, но, возможно, записка для людей, смотрящих на это, как я. Я хотел выполнить определенный код для разных пользователей/клиентов, но также хотел избежать exec / eval. Сначала я искал хранение кода в базе данных для каждого пользователя и делал выше.
Я закончил тем, что создал файлы в файловой системе в папке "customer_filters" и использовал модуль "imp", если для этого клиента не применялся фильтр, он просто выполнял on
import imp
def get_customer_module(customerName='default', name='filter'):
lm = None
try:
module_name = customerName+"_"+name;
m = imp.find_module(module_name, ['customer_filters'])
lm = imp.load_module(module_name, m[0], m[1], m[2])
except:
''
#ignore, if no module is found,
return lm
m = get_customer_module(customerName, "filter")
if m is not None:
m.apply_address_filter(myobj)
so customerName = " jj" выполнит apply_address_filter из customer_filters\jj_filter.py файл
стоит упомянуть, что'execбрат существует также называется execfile Если вы хотите вызвать файл python. Это иногда хорошо, если вы работаете в стороннем пакете, в который включена ужасная IDE, и вы хотите кодировать вне своего пакета.
пример:
execfile('/path/to/source.py)'
или:
exec(open("/path/to/source.py").read())