Как выполнить строку, содержащую код 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.

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

С альтернативы 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 месяцев, вы усложняете его для себя напрямую.


проверить eval:

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

наиболее логичным решением было бы использовать встроенный eval ()


использовать eval.


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())