Преобразование строк в переменные [duplicate]

Обозначение скобок позволяет вам получить доступ к свойствам по имени, хранящимся в переменной:

var obj = { "abc" : "hello" };
var x = "abc";
var y = obj[x];
console.log(y); //output - hello

obj.x не будет работать в этом случае.

244
задан SilentGhost 31 March 2009 в 17:14
поделиться

12 ответов

В примере строка выполняется как код с использованием функции 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()
53
ответ дан hekevintran 25 August 2018 в 11:32
поделиться
  • 1
    меняя меня так, что стюар и stderr очень нервничают. это похоже на то, что это может вызвать серьезные проблемы с безопасностью. есть ли способ обойти это? – Narcolapser 23 May 2011 в 14:33

Хорошо. Я знаю, что это не совсем ответ, но, возможно, записка для людей, которые смотрят на это так, как я. Я хотел выполнить конкретный код для разных пользователей / клиентов, но также хотел избежать 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

0
ответ дан Brian 25 August 2018 в 11:32
поделиться
  • 1
    Как вы управляли безопасностью? Как вы знаете, что клиенты не будут злоупотреблять этой привилегией? – JSBach 14 May 2017 в 15:19

Избегайте exec и eval

Использование exec и eval в Python сильно недооценено.

Существуют лучшие альтернативы

Из главного ответа (выделено мной):

Для операторов используйте exec.

Когда вам нужно значение выражения, используйте eval.

Однако первым шагом должно стать спросить себя, действительно ли вам нужно. Исполняющий код обычно должен быть в крайнем случае: он медленный, уродливый и опасный, если он может содержать введенный пользователем код. Вы всегда должны сначала смотреть на альтернативы, такие как функции более высокого порядка, чтобы увидеть, могут ли они лучше соответствовать вашим потребностям.

Из Альтернативы exec / eval?

установить и получить значения переменных с именами в строках

[пока eval] будет работать, обычно не рекомендуется использовать имена переменных, имеющие значение для самой программы.

Вместо этого лучше использовать dict.

Это не идиоматический

Из http: //lucumr.pocoo

Python не является PHP

Не пытайтесь обойти Идиомы Python, потому что какой-то другой язык делает это по-другому. Пространства имен находятся в Python по какой-то причине, и только потому, что он дает вам инструмент exec, это не значит, что вы должны использовать этот инструмент.

Это опасно

From http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html (выделение мое)

Таким образом, eval небезопасен, даже если вы удалите все глобальные и встроенные функции!

Проблема со всеми этими попытками защитить eval () заключается в том, что они являются черными списками. Они явно удаляют вещи, которые могут быть опасными. Это проигравшая битва, потому что, если из списка осталось только один элемент, вы можете атаковать систему.

Итак, можно ли сделать eval безопасным? Сложно сказать. На этом этапе я думаю, что вы не можете навредить, если не можете использовать двойные подчеркивания, поэтому, возможно, если вы исключите любую строку с двойными подчеркиваниями, вы будете в безопасности. Может быть ...

Трудно читать и понимать

Из http://stupidpythonideas.blogspot.it/2013/05/why-evalexec -is-bad.html (акцент мой):

Во-первых, exec затрудняет чтение человеком вашего кода. Чтобы выяснить, что происходит, мне не нужно просто читать ваш код, я должен прочитать ваш код, выяснить, какую строку он будет генерировать, а затем прочитать этот виртуальный код. Итак, если вы работаете в команде или публикуете программное обеспечение с открытым исходным кодом или просите о помощи где-то вроде StackOverflow, вам становится труднее помочь другим людям. И если есть вероятность, что вы собираетесь отлаживать или расширять этот код через 6 месяцев, вам становится труднее для себя непосредственно.

7
ответ дан Community 25 August 2018 в 11:32
поделиться
  • 1
    «Моя лучшая догадка заключается в том, что вы не можете навредить, если не можете использовать двойные подчеркивания». - Вы можете построить строку, содержащую двойные символы подчеркивания, а затем вызвать eval для этой строки. – Stanley Bak 11 October 2016 в 16:11
  • 2
    Ваш текст имеет много форм. – user1767754 2 January 2018 в 01:38

Для операторов используйте 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

Однако первым шагом должно стать спросить себя, действительно ли вам нужно. Исполняющий код обычно должен быть в крайнем случае: он медленный, уродливый и опасный, если он может содержать введенный пользователем код. Вы всегда должны сначала взглянуть на альтернативы, такие как функции более высокого порядка, чтобы узнать, могут ли они лучше соответствовать вашим потребностям.

242
ответ дан Helen 25 August 2018 в 11:32
поделиться
  • 1
    но как насчет объема кода, выполняемого 'exec'? он вложен? – jondinham 6 March 2012 в 12:24
  • 2
    Частым случаем, когда кто-то хочет использовать «exec», является что-то вроде 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
  • 3
    Как exec медленнее, чем интерпретатор python? – Cris Stringfellow 6 February 2013 в 18:36
  • 4
    @ShreevatsaR Вы не имеете в виду setattr(x, s, 42)? Я попробовал getattr(x, 2) = 42, и он не сработал с can't assign to function call: <string>, line 1 – Tanner Semerad 11 October 2013 в 18:44
  • 5
    @ Таннер: Хмм. Да, действительно setattr(x, s, 42) - правильный синтаксис. Удивленный, для этой ошибки нужно было так долго ловить. Во всяком случае, дело в том, что getattr и setattr являются альтернативой exec, когда все, что вам нужно, - это получить произвольный член, искаженный строкой. – ShreevatsaR 11 October 2013 в 20:01

eval() предназначен только для выражений, а eval('x+1') работает, eval('x=1') не работает, например. В этом случае лучше использовать exec или даже лучше: попытайтесь найти лучшее решение:)

11
ответ дан Jérôme Verstrynge 25 August 2018 в 11:32
поделиться

Наиболее логичным решением было бы использовать встроенную функцию eval () . Другое решение - записать эту строку во временный файл python и выполнить ее.

3
ответ дан John T 25 August 2018 в 11:32
поделиться

Помните, что из версии 3 exec является функцией! поэтому всегда используйте exec(mystring) вместо exec mystring.

19
ответ дан Kevin Guan 25 August 2018 в 11:32
поделиться

Вы выполняете выполнение кода с помощью exec, как со следующим сеансом IDLE:

>>> kw = {}
>>> exec( "ret = 4" ) in kw
>>> kw['ret']

4
9
ответ дан octopusgrabbus 25 August 2018 в 11:32
поделиться
  • 1
    Это не работает в обычном питоне. По крайней мере, не в python 3. – Thomas Ahle 20 August 2018 в 11:22

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

По сути вы определяете пространство имен, в котором будет выполняться код.

17
ответ дан osa 25 August 2018 в 11:32
поделиться
  • 1
    Невозможно сделать eval safe: Eval действительно опасен . Если вы возьмете код от меня и оцените его, я могу выполнить вашу программу Python. Игра закончена. – Ned Batchelder 18 February 2013 в 06:20
  • 2
    @NedBatchelder: это не более опасно. в вашей ссылке rm /rf. так мы должны сказать, что bash опасен, потому что мы можем это сделать? единственной проблемой являются атаки на высоту. Но мы не заботимся об этом, если скрипт не является удаленной службой (т. Е. Если это просто что-то выполнено вами). – v.oddou 13 January 2015 в 04:41
  • 3
    @ v.oddou Я отвечал утверждению Алана, «eval и exec .. можно использовать безопасным образом». Это неверно. Если кто-то сказал, «bash можно использовать безопасным образом», это также было бы ложным. Баш опасен. Это опасная, но опасная опасность. Утверждение, что eval может быть безопасным, просто неверно. – Ned Batchelder 13 January 2015 в 16:10
  • 4
    @NedBatchelder да, действительно. и ссылка, на которую вы указываете, является хорошим материалом. с властью приходит ответственность, поэтому дело просто в том, чтобы знать о потенциальной силе eval. и если мы решим, что власть = опасность. – v.oddou 14 January 2015 в 03:08
  • 5
    @NedBatchelder Многие фрагменты кода, написанные на Python, также могут быть опасны, но почему вы предполагаете, что eval или exec предназначены для использования как exec(input("Type what you want"))? Существует много случаев, когда программа может написать процедуру или функцию в результате вычисления; результирующие функции будут такими же безопасными и быстрыми (после оценки), как любая другая часть хорошей и хорошо написанной программы. Небезопасная программа, содержащая exec, не более опасна, чем небезопасная программа, наносящая ущерб самому себе, поскольку exec не дает никаких новых привилегий для программы. – Thomas Baruchel 16 November 2016 в 11:46

Используйте eval .

1
ответ дан Pablo Santa Cruz 25 August 2018 в 11:32
поделиться

Проверьте eval :

x = 1
print eval('x+1')
->2
3
ответ дан ryeguy 25 August 2018 в 11:32
поделиться

Стоит упомянуть, что брат [exec] также называется execfile, если вы хотите вызвать файл python. Иногда бывает хорошо, если вы работаете в стороннем пакете, в котором есть ужасная IDE, и вы хотите закодировать вне своего пакета.

Пример:

execfile('/path/to/source.py)'

или:

exec(open("/path/to/source.py").read())

0
ответ дан user1767754 25 August 2018 в 11:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: