Обозначение скобок позволяет вам получить доступ к свойствам по имени, хранящимся в переменной:
var obj = { "abc" : "hello" };
var x = "abc";
var y = obj[x];
console.log(y); //output - hello
obj.x
не будет работать в этом случае.
В примере строка выполняется как код с использованием функции 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()
Хорошо. Я знаю, что это не совсем ответ, но, возможно, записка для людей, которые смотрят на это так, как я. Я хотел выполнить конкретный код для разных пользователей / клиентов, но также хотел избежать exec / eval. Сначала я искал сохранение кода в базе данных для каждого пользователя и делал это.
В итоге я создал файлы в файловой системе в папке «customer_filters» и использовал модуль «imp», если ни один фильтр не применяется для этого клиента, он просто переносится на
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)
, поэтому customerName = "jj" выполнит apply_address_filter из файла customer_filters \ jj_filter.py
exec
и eval
exec
и eval
в Python сильно недооценено. Из главного ответа (выделено мной):
Для операторов используйте
exec
.Когда вам нужно значение выражения, используйте
eval
.Однако первым шагом должно стать спросить себя, действительно ли вам нужно. Исполняющий код обычно должен быть в крайнем случае: он медленный, уродливый и опасный, если он может содержать введенный пользователем код. Вы всегда должны сначала смотреть на альтернативы, такие как функции более высокого порядка, чтобы увидеть, могут ли они лучше соответствовать вашим потребностям.
blockquote>установить и получить значения переменных с именами в строках
[пока
eval
] будет работать, обычно не рекомендуется использовать имена переменных, имеющие значение для самой программы.Вместо этого лучше использовать dict.
blockquote>Это не идиоматический
Python не является PHP
Не пытайтесь обойти Идиомы Python, потому что какой-то другой язык делает это по-другому. Пространства имен находятся в Python по какой-то причине, и только потому, что он дает вам инструмент
blockquote>exec
, это не значит, что вы должны использовать этот инструмент.Это опасно
From http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html (выделение мое)
Таким образом, eval небезопасен, даже если вы удалите все глобальные и встроенные функции!
Проблема со всеми этими попытками защитить eval () заключается в том, что они являются черными списками. Они явно удаляют вещи, которые могут быть опасными. Это проигравшая битва, потому что, если из списка осталось только один элемент, вы можете атаковать систему.
Итак, можно ли сделать eval безопасным? Сложно сказать. На этом этапе я думаю, что вы не можете навредить, если не можете использовать двойные подчеркивания, поэтому, возможно, если вы исключите любую строку с двойными подчеркиваниями, вы будете в безопасности. Может быть ...
blockquote>Трудно читать и понимать
Из http://stupidpythonideas.blogspot.it/2013/05/why-evalexec -is-bad.html (акцент мой):
Во-первых,
blockquote>exec
затрудняет чтение человеком вашего кода. Чтобы выяснить, что происходит, мне не нужно просто читать ваш код, я должен прочитать ваш код, выяснить, какую строку он будет генерировать, а затем прочитать этот виртуальный код. Итак, если вы работаете в команде или публикуете программное обеспечение с открытым исходным кодом или просите о помощи где-то вроде StackOverflow, вам становится труднее помочь другим людям. И если есть вероятность, что вы собираетесь отлаживать или расширять этот код через 6 месяцев, вам становится труднее для себя непосредственно.
Для операторов используйте 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
Однако первым шагом должно стать спросить себя, действительно ли вам нужно. Исполняющий код обычно должен быть в крайнем случае: он медленный, уродливый и опасный, если он может содержать введенный пользователем код. Вы всегда должны сначала взглянуть на альтернативы, такие как функции более высокого порядка, чтобы узнать, могут ли они лучше соответствовать вашим потребностям.
if s=='foo': x.foo = 42 elif s=='bar': x.bar = 42
и т. Д., Которое они могут записать как exec ("x.%s = 42" % s)
. Для этого общего случая (когда вам нужно только получить доступ к атрибуту объекта, который хранится в строке), существует намного более быстрая, более чистая и безопасная функция getattr
: просто напишите getattr(x, s) = 42
, чтобы означать одно и то же.
– ShreevatsaR
19 April 2012 в 20:18
setattr(x, s, 42)
? Я попробовал getattr(x, 2) = 42
, и он не сработал с can't assign to function call: <string>, line 1
– Tanner Semerad
11 October 2013 в 18:44
setattr(x, s, 42)
- правильный синтаксис. Удивленный, для этой ошибки нужно было так долго ловить. Во всяком случае, дело в том, что getattr
и setattr
являются альтернативой exec
, когда все, что вам нужно, - это получить произвольный член, искаженный строкой.
– ShreevatsaR
11 October 2013 в 20:01
eval()
предназначен только для выражений, а eval('x+1')
работает, eval('x=1')
не работает, например. В этом случае лучше использовать exec
или даже лучше: попытайтесь найти лучшее решение:)
Наиболее логичным решением было бы использовать встроенную функцию eval () . Другое решение - записать эту строку во временный файл python и выполнить ее.
Помните, что из версии 3 exec
является функцией! поэтому всегда используйте exec(mystring)
вместо exec mystring
.
Вы выполняете выполнение кода с помощью exec, как со следующим сеансом IDLE:
>>> kw = {}
>>> exec( "ret = 4" ) in kw
>>> kw['ret']
4
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
По сути вы определяете пространство имен, в котором будет выполняться код.
rm /rf
. так мы должны сказать, что bash опасен, потому что мы можем это сделать? единственной проблемой являются атаки на высоту. Но мы не заботимся об этом, если скрипт не является удаленной службой (т. Е. Если это просто что-то выполнено вами).
– v.oddou
13 January 2015 в 04:41
eval
или exec
предназначены для использования как exec(input("Type what you want"))
? Существует много случаев, когда программа может написать процедуру или функцию в результате вычисления; результирующие функции будут такими же безопасными и быстрыми (после оценки), как любая другая часть хорошей и хорошо написанной программы. Небезопасная программа, содержащая exec
, не более опасна, чем небезопасная программа, наносящая ущерб самому себе, поскольку exec
не дает никаких новых привилегий для программы. i>
– Thomas Baruchel
16 November 2016 в 11:46
Стоит упомянуть, что брат [exec
] также называется execfile
, если вы хотите вызвать файл python. Иногда бывает хорошо, если вы работаете в стороннем пакете, в котором есть ужасная IDE, и вы хотите закодировать вне своего пакета.
Пример:
execfile('/path/to/source.py)'
или:
exec(open("/path/to/source.py").read())