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

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

Ответ 1

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

Ответ 2

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

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

Ответ 3

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

Ответ 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

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

Ответ 5

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

Ответ 6

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

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

4

Ответ 7

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

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

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

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

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

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

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

От альтернатив к 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() заключается в том, что они являются черными списками. Они явно удаляют вещи, которые могут быть опасными. Это проигравшая битва, потому что если в списке остался только один элемент, вы можете атаковать систему.

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

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

С http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (основное внимание):

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

Ответ 8

Отъезд eval:

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

Ответ 9

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

Ответ 10

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

Ответ 11

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

Ответ 12

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

Пример:

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

или же:

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