Использование eval в Python?

Есть eval() Функция в Python, на которую я наткнулся во время игры. Я не могу представить себе случай, когда эта функция нужна, за исключением, может быть, синтаксического сахара. Кто-нибудь может привести пример?

13 ответов

Решение

eval а также exec удобный быстрый и грязный способ получить некоторый исходный код динамически, может быть, немного изменить его, а затем выполнить его, но вряд ли он когда-либо будет лучшим способом, особенно в производственном коде, в отличие от "быстрого и грязного" прототипы и пр.

Например, если бы мне пришлось иметь дело с такими динамическими исходниками Python, я бы достал модуль ast - ast.literal_eval НАМНОГО безопаснее, чем eval (вы можете вызвать его непосредственно в строковой форме выражения, если оно одноразовое и зависит только от простых констант, или сделать node = ast.parse(source) сначала сохраните node где-то, возможно, возьмите его с подходящими посетителями, например для поиска переменных, затем literal_eval узел) - или, однажды приведя узел в надлежащую форму и проверив его на наличие проблем безопасности, я мог бы compile это (получая объект кода) и построить новый объект функции из этого. Гораздо менее просто (за исключением того, что ast.literal_eval так же просто, как eval для самых простых случаев!) но безопаснее и предпочтительнее в коде производственного качества.

Для многих задач, которые я видел, люди (ab-) используют exec а также eval для, мощные встроенные модули Python, такие как getattr а также setattr, индексируя в globals(), &c, предоставляют предпочтительные и на самом деле часто более простые решения. Для конкретных целей, таких как анализ JSON, библиотечные модули, такие как json лучше (например, см. комментарий SilentGhost к ответу на шум в ушах на этот самый вопрос). И т. Д., И т. Д.

Статья в Википедии оeval довольно информативен, и детализирует различные варианты использования.

Вот некоторые варианты использования:

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

В прошлом я использовал eval() для добавления интерфейса отладки в мое приложение. Я создал службу telnet, которая поместила вас в среду запущенного приложения. Входные данные проходили через eval(), поэтому вы можете интерактивно запускать команды Python в приложении.

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

a=10.0
b=5.0
c=math.log10(a/b)

Синтаксический анализатор python прочитал этот входной файл и получил окончательные данные, оценивая значения и выражения с помощью eval().

Я не утверждаю, что это хорошее программирование, но мне не нужно было управлять ядерным реактором.

Я использую его как быстрый JSON-парсер...

r='''
{
    "glossary": {
        "title": "example glossary"
        }
}
'''

print eval(r)['glossary']['title']

Вы можете использовать eval в декораторе:

#this replaces the original printNumber with a lambda-function,
#which takes no arguments and which calls the old function with
#the number 10
@eval("lambda fun: lambda: fun(10)")
def printNumber(i: int) -> None:
    print("The number is %i", i)

#call
printNumber()

в то время как вы не можете использовать сложные выражения, такие как

@lambda fun: lambda: fun(10)
def ...

ни

@(lambda fun: lambda: fun(10))
def ...

Вы не можете использовать лямбда-выражение там, потому что декоратор должен быть либо идентификатором:

@myModule.functionWithOneArg

или вызов функции:

@functionReturningFunctionWithOneArg(any, "args")

Вы видите, что вызов функции eval со строкой имеет здесь правильный синтаксис, а лямбда-выражение - нет. (-> https://docs.python.org/3/reference/compound_stmts.html)

Я только что нашел хорошее применение eval. Я писал набор тестов для некоторого кода и создал класс Test, где каждый метод представлял собой тест, который нужно запустить. Мне нужен был способ, чтобы я мог запускать все тестовые методы без необходимости вызывать каждый метод отдельно. Итак, я написал что-то довольно грязное.

class Test:
    def __init__(self, *args):
       #bs

    def test1(self):
       #bs

    def test2(self):
       #bs

if __name__ == "__main__":
    import argparse
    #argparse bs
    test = Test(*bs_args)
    for func in (i for i in dir(test) if i[0] != '_' and i not in test.__dict__):
        print(eval('test.{func}()'.format(func = func)))

Динамическая оценка произвольных тестовых случаев довольно крутая. Мне просто нужно написать метод, и после сохранения я могу включить метод в свой набор тестов. Что касается кода, я в основном просто проверяю методы, определенные в тестовом объекте, и проверяю, что они не являются "магическими" методами или атрибутами python по умолчанию для тестового объекта. После этого я могу предположить, что они являются методами и могут быть оценены.

Eval - это способ взаимодействия с интерпретатором Python из программы. Вы можете передавать литералы в eval, и он оценивает их как выражения Python.

Например -

print eval("__import__('os').getcwd()")

вернул бы текущий рабочий каталог.

ура

eval() обычно не очень полезен. Одна из немногих вещей, которые я использовал для этого (ну, это было exec() на самом деле, но это довольно похоже) позволяло пользователю создавать сценарии приложения, которое я написал на Python. Если бы он был написан на чем-то вроде C++, мне бы пришлось встроить интерпретатор Python в приложение.

eval() для одного предложения, а exec() для нескольких.

обычно мы используем их для добавления или посещения некоторых скриптов, таких как bash shell.

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

У меня был случай, когда я использовал eval в сочетании с базой данных informix. По какой-то причине запрос вернул строку, подобную этой

query_result = "['1', '2', '3']"

Я просто использовал eval для результата запроса, поэтому python интерпретировал его как список строк.

[int(i) for i in eval(query_result)]
> [1,2,3]

Я не мог изменить базу данных, поэтому это был быстрый (и грязный) способ получить целые числа.

Я использовал его для ввода значений переменных в основную программу:

test.py var1 = 2 var2 = True

...

var1=0
var2=False
for arg in sys.argv[1:]:
    exec(arg)

Грубый способ разрешить использование ключевых слов в основной программе. Если есть лучший способ, дайте мне знать!

Я использую exec создать систему плагинов в Python.

    пытаться:
        exec ("from " + plugin_name + " import Plugin")
        myplugin = плагин (module_options, config=config)
    кроме ImportError, сообщение:
        фатальный ("Нет такого модуля" + plugin_name + \
               " (или нет конструктора плагинов) в моем пути Python:" + str (message))
    кроме исключения:
        фатальный ("Module " + plugin_name + "не может быть загружен: " + \
               str(sys.exc_type) + ": " + str(sys.exc_value) + \
               ".\n Может быть, отсутствует или ошибочен?"

С плагином вроде:

Плагин класса:

    def __init__ (self):
        проходить

    запрос def (self, arg):...

Вы сможете назвать это как:

    result = myplugin.query ("что-то")

Я не думаю, что вы можете иметь плагины в Python без exec/eval,

Другие вопросы по тегам