it-swarm.com.ru

Как мне выполнить строку, содержащую код Python в Python?

Как мне выполнить строку, содержащую код Python в Python?

270
hekevintran

В этом примере строка выполняется как код с использованием функции 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()
57
hekevintran

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

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

262
Brian

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

19
bheks

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

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

18
alan

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

11
LGB

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

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

4
9
gus

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

Использование exec и eval в Python весьма неодобрительно.

Есть лучшие альтернативы

С верху ответ (акцент мой):

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

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

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

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

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

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

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

Это не идиоматично

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

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

От http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (выделено мной):

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

9
Caridorc

Проверить Eval :

x = 1
print eval('x+1')
->2
4
ryeguy

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

3
John T

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

2
Pablo Santa Cruz

Как уже упоминалось, это "exec" .. 

но, если ваш код содержит переменные, вы можете использовать «глобальный» для доступа к нему, а также, чтобы компилятор не вызвал следующую ошибку:

NameError: имя 'p_variable' не определено

exec('p_variable = [1,2,3,4]')
global p_variable
print(p_variable)
1
Ghanem

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

Пример:

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

или же:  

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

1
user1767754

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