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

StackOverflow https://stackoverflow.com/questions/701802

  •  22-08-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение 2

В примере строка выполняется как код с использованием функции 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(string) (Python 2/3) или exec string (Python 2):

>>> mycode = 'print "hello world"'
>>> exec(mycode)
Hello world

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

>>> x = eval("2+2")
>>> x
4

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

eval и exec являются правильным решением, и их можно использовать в безопаснее манера поведения.

Как обсуждалось в Справочное руководство по Python и четко объяснено в это учебное пособие, the 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

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

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

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

Избегать exec и eval

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

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

Из верхнего ответа (курсив мой):

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

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

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

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

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

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

Это трудно прочесть и понять

От http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (курсив мой):

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

Вы завершаете выполнение кода с помощью exec, как и в следующем сеансе ОЖИДАНИЯ:

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

4

Использование оценка.

Проверьте оценка:

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

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

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

Пример:

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

или:

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

Как упоминали другие, это "exec" ..

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

Ошибка имени:имя 'p_variable' не определено

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

ОК..Я знаю, что это не совсем ответ, но, возможно, замечание для людей, смотрящих на это так же, как и я.Я хотел выполнить определенный код для разных пользователей / заказчиков, но также хотел избежать 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 = "й" выполнить apply_address_filter из файла customer_filters\jj_filter.py

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top