Как использовать метод eval() в Python?
Метод eval() анализирует выражение, переданное этому методу, и запускает выражение (код) Python внутри программы.
Проще говоря, функция eval() запускает код Python (который передается в качестве аргумента) в программе.
Функция eval() принимает три параметра:
Метод eval() возвращает результат, вычисленный на основе выражения.
Пример 1
Здесь функция eval() вычисляет выражение x + 1, и print используется для отображения этого значения.
Пример 2
Предупреждения при использовании eval()
Рассмотрим ситуацию, когда вы используете систему Unix (macOS, Linux и т. Д.) И импортировали модуль ОС. Модуль os предоставляет переносимый способ использования функций операционной системы, таких как чтение или запись в файл.
Если вы используете eval (input()) в своем коде, рекомендуется проверить, какие переменные и методы может использовать пользователь. Вы можете увидеть, какие переменные и методы доступны, используя метод dir().
Ограничение использования доступных методов и переменных в eval()
Чаще всего все доступные методы и переменные, используемые в выражении (первый параметр eval()), могут не понадобиться или даже могут иметь брешь в безопасности. Возможно, вам придется ограничить использование этих методов и переменных для eval(). Вы можете сделать это, передав необязательные глобальные и локальные параметры (словари) в функцию eval().
1 Если опущены и глобальные, и локальные параметры
Если оба параметра опущены (как в наших предыдущих примерах), выражение выполняется в текущей области. Вы можете проверить доступные переменные и методы, используя следующий код:
2 Передача глобальных параметров
Примечание. Вы можете проверить текущий глобальный и локальный словарь в Python, используя встроенные методы globals() и locals() соответственно.
3 Передача пустого словаря в качестве параметра глобальных переменных
Несмотря на то, что мы импортировали математический модуль в приведенную выше программу, выражение не может получить доступ к функциям, предоставляемым математическим модулем.
4 Обеспечение доступности определенных методов
Здесь выражение может использовать только методы sqrt() и pow() вместе с __builtins__.
Также можно изменить имя метода, доступного для выражения, по вашему желанию:
В приведенной выше программе square_root() вычисляет квадратный корень с помощью sqrt(). Однако попытка использовать sqrt() напрямую вызовет ошибку.
5 Ограничение использования встроенных модулей
Вы можете ограничить использование __builtins__ в выражении следующим образом:
3 Передача как глобальных, так и локальных словарей
Вы можете сделать необходимые функции и переменные доступными для использования, передав словарь locals. Например:
В этой программе выражение может иметь только метод sqrt() и переменную a. Все остальные методы и переменные недоступны.
Ограничение использования eval() путем передачи глобальных и локальных словарей сделает ваш код безопасным, особенно когда вы используете ввод, предоставленный пользователем методу eval().
Примечание. Иногда eval() небезопасен даже с ограниченными именами. Когда объект и его методы становятся доступными, можно делать практически все. Единственный безопасный способ — это проверить введенные пользователем данные.
Функция Eval
Функция Eval используется для оценки выражение, которая приводит к в виде текстовой строки или числового значения.
Вы можете составить строку и передать ее функции Eval точно так же, как если бы эта строка была настоящим выражением. Функция Eval вычисляет строковое выражение и возвращает его значение. Например, Eval(«1 + 1») возвращает 2.
Если в функцию Eval передать строку, содержащую имя другой функции, функция Eval вернет значение, возвращаемое этой функцией. Например, Eval(«Chr$(65)») возвращает значение «A».
Аргумент строковое_выражение — это выражение, результатом вычисления которого является строка, состоящая из букв и цифр. В качестве строкового_выражения можно, например, указать функцию, которая возвращает строку или числовое значение. В других случаях это может быть ссылка на элемент управления формы. Аргумент строковое_выражение должен в результате вычисления давать строковое или числовое значение; его результатом не может быть объект объект Microsoft Access.
Примечание: В примерах ниже показано, как использовать эту функцию в модуле Visual Basic для приложений (VBA). Чтобы получить дополнительные сведения о работе с VBA, выберите Справочник разработчика в раскрывающемся списке рядом с полем Поиск и введите одно или несколько слов в поле поиска.
Примечание: Если вы указываете в аргументе строковое_выражение функции Eval имя другой функции, необходимо ставить после него в скобки. Например:
Debug.Print Eval(«StrComp(«»Joe»»,»»joe»», 1)»)
Замечания
Функцию Eval можно использовать в вычисляемый элемент управления в форме, отчете, макросах или модулях. Функция Eval возвращает variant, который является строкой или числом.
Аргументом строковое_выражение должно быть выражение, сохраненное в строке. Если функции Eval передать строку, которая содержит только текст, а не числовое выражение или имя функции, возникнет ошибка во время выполнения. Например, выполнение функции Eval(«Smith») приведет к ошибке.
С помощью функции Eval можно определить значение, хранящееся в свойстве Значение элемента управления. В следующем примере в функцию Eval передается строка, содержащая полную ссылку на элемент управления. В диалоговом окне будет отображаться текущее значение элемента управления.
Функция Eval дает возможность применять операторы выражений, недопустимые в модулях Visual Basic для приложений (VBA). Например, в коде программы нельзя использовать непосредственно операторы SQL Between. And или In, но их можно использовать в выражении, передаваемом в функцию Eval.
В следующем примере определяется, является ли значение элемента управления ShipRegion (Регион доставки) в форме Orders (Заказы) одним из заданных кодов регионов. Если поле содержит одно из таких обозначений, переменная intState примет значение True (-1). Обратите внимание, что для включения одной строки в другую нужно использовать одинарные кавычки (‘).
Примеры запросов
SELECT Eval(«15+3») AS Expr1 FROM ProductSales GROUP BY Eval(«15+3»);
Вычисляет строковую величину и результат. Результат: 18.
SELECT Eval(«Date()+month(date()))») AS NewDate FROM ProductSales Group by Eval(«Date()+month(date())»);
Оценивает строковую величину, определяет функции и выполняет их. Результат: текущая системная дата + текущий месяц, отображаемая в столбце NewDate.
Примеры VBA
В следующем примере предполагается, что имеется 50 функций, обозначенных A1, A2 и т. д. Функция Eval используется для последовательного вызова этих функций.
В следующем примере событие «Щелкните» активируется так же, как если бы пользователь нажал кнопку в форме. Если значение свойства OnClick кнопки начинается со знака равной (=), то есть это имя функции, функция Eval вызывает функцию, что эквивалентно запуску события Click. Если значение не начинается со знака равно, ему необходимо назвать макрос. Метод RunMacro объекта DoCmd выполняет именуемый макрос.
Eval: выполнение строки кода
Встроенная функция eval позволяет выполнять строку кода.
Строка кода может быть большой, содержать переводы строк, объявления функций, переменные и т.п.
Результатом eval будет результат выполнения последней инструкции.
Код в eval выполняется в текущем лексическом окружении, поэтому ему доступны внешние переменные:
Значения внешних переменных можно изменять:
Без use strict у eval не будет отдельного лексического окружения, поэтому x и f будут видны из внешнего кода.
Использование «eval»
В современной разработке на JavaScript eval используется весьма редко. Есть даже известное выражение – «eval is evil» («eval – это зло»).
Пожалуйста, имейте в виду, что код в eval способен получать доступ к внешним переменным, и это может иметь побочные эффекты.
Использование внутри eval локальных переменных из внешнего кода считается плохим решением, так как это усложняет задачу по поддержке такого кода.
Существует два пути, как гарантированно избежать подобных проблем.
Если код внутри eval не использует внешние переменные, то вызывайте его так – window.eval(. ) :
В этом случае код выполняется в глобальной области видимости:
Если коду внутри eval нужны локальные переменные, поменяйте eval на new Function и передавайте необходимые данные как аргументы:
Конструкция new Function объясняется в главе Синтаксис «new Function». Она создаёт функцию из строки в глобальной области видимости. Так что локальные переменные для неё невидимы, но всегда можно передать их как аргументы. Получается очень аккуратный код, как в примере выше.
Итого
Вызов eval(code) выполняет строку кода и возвращает результат последней инструкции.
Задачи
Eval-калькулятор
Создайте калькулятор, который запрашивает ввод какого-нибудь арифметического выражения и возвращает результат его вычисления.
В этой задаче нет необходимости проверять полученное выражение на корректность, просто вычислить и вернуть результат.
Давайте будем использовать eval для вычисления арифметических выражений:
Что делает функция eval
Метод eval() выполняет JavaScript-код, представленный строкой.
Синтаксис
Параметры
Возвращаемое значение
Описание
Н е используйте eval без необходимости!
Также eval(), как правило, медленнее альтернатив, так как вызывает интерпретатор JS, тогда как многие другие конструкции оптимизированы современными JS движками.
Есть безопасные (и быстрые!) альтернативы eval() для общих случаев использования.
Доступ к свойствам
Однако, eval() здесь не нужен. По факту, использование здесь его удивляет. Вместо него используйте доступ к свойствам, который быстрее и безопаснее:
Используйте функции вместо исполнения фрагментов кода
У JavaScript функции первого класса, что значит, что вы можете передавать функции как аргументы, хранить их в переменных или свойствах объектов и так далее. Многие DOM API созданы с учётом этого, так что вы можете (и вам следует) писать:
Замыкания также полезны как способ создания функций с параметрами без конкатенации строк.
Разбор JSON (конвертирование строк в JavaScript объекты)
Заметьте, что синтаксис JSON ограничен в сравнении с JavaScript синтаксисом, многие валидные JavaScript литералы не распарсятся в JSON. К примеру, лишние запятые в конце выражений не разрешены в JSON, а имена свойств (ключи) в объектах должны быть в двойных кавычках. Будьте уверены использовать сериализацию JSON для создания строк, которые потом будут разбираться как JSON.
Передавайте данные вместо кода
К примеру, расширение, созданное изменять содержимое веб-страниц, должно иметь правила, определённые в XPath, а не JS коде.
Выполняйте код с ограниченными правами
Если выполнять код всё-таки необходимо, желательно это делать с уменьшенными привелегиями. Этот совет подходит, главным образом, к расширениям и XUL приложениям, которые могут использовать Components.utils.evalInSandbox.
Примеры
Использование eval
Использование eval для исполнения строки, содержащей операторы JavaScript
Последнее выражение выполняется
eval() вернёт значение последнего выполняемого выражения
eval как строковое определение функции, включающее «(» и «)» как префикс и суффикс
Спецификации
Поддержка браузерами
BCD tables only load in the browser
Gecko-специфичные замечания
Смотрите также
Found a problem with this page?
Mozilla
© 2005- 2021 Mozilla and individual contributors. Content is available under these licenses.
Динамическое выполнение выражений в Python: eval()
Функция eval() полезна, когда необходимо выполнить динамически обновляемое выражение Python из какого-либо ввода (например, функции input() ), представленного в виде строки или объекта байт-кода. Это невероятно полезный инструмент, но то, что она может выполнять программный код, имеет важные последствия для безопасности, которые следует учесть перед ее применением.
Статья является сокращенным переводом публикации Леоданиса Посо Рамоса Python eval(): Evaluate Expressions Dynamically. Из этого руководства вы узнаете:
Разбираемся в том, как работает eval()
Вы можете использовать встроеннyю функцию eval() для динамического исполнения выражений из ввода на основе строки или скомпилированного кода. Если вы передаете в eval() строку, то функция анализирует ее, компилирует в байт-код и выполняет как выражение Python.
Сигнатура eval() определена следующим образом:
Первый аргумент: expression
При вызове eval() со строковым выражением в качестве аргумента, функция возвращает значение, полученное в результате оценки входной строки. По умолчанию eval() имеет доступ к глобальным именам, таким как x в приведенном выше примере.
Чтобы оценить строковое выражение, eval() выполняет следующую последовательность действий:
Имя аргумента expression подчеркивает, что функция работает только с выражениями, но не составными конструкциями. При попытке передачи блока кода вместо выражения будет получено исключение SyntaxError :
В eval() запрещены и операции присваивания:
SyntaxError также вызывается в случаях, когда eval() не удается распарсить выражение из-за ошибки в записи:
Таким образом, мы можем использовать compile() для предоставления объектов кода в eval() вместо обычных строк:
Использование объектов кода полезно при многократном вызове. Если мы предварительно скомпилируем входное выражение, то последующие вызовы eval() будут выполняться быстрее, так как не будут повторяться шаги синтаксического анализа и компиляции.
Второй аргумент: globals
Глобальные имена – это все те имена, которые доступны в текущей глобальной области или пространстве имен. Вы можете получить к ним доступ из любого места в вашем коде.
Все имена, переданные глобальным переменным в словаре, будут доступны eval() во время выполнения.
Вы также можете указать имена, которых нет в текущей глобальной области видимости. Чтобы это работало, нужно указать конкретное значение для каждого имени. Тогда eval() будет интерпретировать эти имена, как если бы это были глобальные переменные:
Несмотря на переданный пустой словарь ( <> ), eval() имеет доступ к встроенным функциям.
При вызове eval() без передачи пользовательского словаря в глобальные переменные аргумент по умолчанию будет использовать словарь, возвращаемый globals() в среде, где вызывается eval() :
Третий аргумент: locals
Аргумент locals также является необязательным аргументом. В этом случае словарь содержит переменные, которые eval() использует в качестве локальных имен при оценке выражения.
Локальными называются те имена (переменные, функции, классы и т.д.), которые мы определяем внутри данной функции. Локальные имена видны только изнутри включающей функции.
Выполнение выражений с eval()
Функция eval() используется, когда нужно динамически изменять выражения, а применение других техник и инструментов Python требует избыточных усилий. В этом разделе мы обсудим, как использовать eval() для булевых, математических и прочих выражений Python.
Булевы выражения
Булевы выражения – это выражения Python, которые возвращают логическое значение. Обычно они используются для проверки, является ли какое-либо условие истинным или ложным:
Зачем же может потребоваться использовать eval() вместо непосредственного применения логического выражения? Предположим, нам нужно реализовать условный оператор, но вы хотите на лету менять условие:
Теперь представьте, как бы вы реализовали то же поведение без eval() для обработки любого логического выражения.
Математические выражения
Выражения общего вида
Вы можете использовать eval() и с более сложными выражениями Python, включающими вызовы функций, создание объектов, доступ к атрибутам и т. д.
Например, можно вызвать встроенную функцию или функцию, импортированную с помощью стандартного или стороннего модуля. В следующих примерах eval() используется для запуска различных системных команд.
Таким образом, можно передавать команды через какой-либо строковый интерфейс (например, форму в браузере) и выполнять код Python.
Минимизация проблем безопасности, связанных с eval()
Если вы используете Linux и приложения имеет необходимые разрешения, то злонамеренный пользователь может ввести опасную строку, подобную следующей:
Выполнение выражения удалит все файлы в текущей директории.
Ограничение globals и locals
Ограничение __builtins__
Чтобы минимизировать риски, можно переопределить __builtins__ в globals :
Ограничение имён во входных данных
Этот код напечатает большой список классов. Некоторые из этих классов довольно мощные и могут быть чрезвычайно опасны в чужих руках. Это открывает еще одну важную дыру в безопасности, которую вы не сможете закрыть, просто ограничивая окружение eval() :
Возможное решение этой уязвимости состоит в том, чтобы ограничить использование имен во входных данных набором безопасных имен либо исключить всякое использование любых имен.
Чтобы реализовать эту технику, необходимо выполнить следующие шаги:
Взглянем на следующую функцию, в которой реализованы все эти шаги:
Следующие примеры показывают, как написанная нами функция eval_expression() работает на практике:
Если нужно полностью запретить применение имен, достаточно переписать eval_expression() следующим образом:
Ограничение входных данных до литералов
Использование eval() совместно с input()
В Python 3.x встроенная функция input() читает пользовательский ввод из командной строки, преобразует его в строку, удаляет завершающий символ новой строки и возвращает результат вызывающей стороне. Поскольку результатом input() является строка, ее можно передать в eval() и выполнить как выражение Python:
Построим обработчик математических выражений
Итак, мы узнали, как работает eval() в Python и как использовать функцию на практике. Мы также выяснили, что eval() имеет важные последствия для безопасности и что обычно считается хорошей практикой избегать использования eval() в коде. Однако в некоторых ситуациях eval() может сэкономить много времени и усилий.
Модуль math мы используем для того, чтобы определить все доступные имена. Три строковые константы применяются для вывода строк в интерфейсе программы. Напишем ключевую функцию нашей программы:
Осталось лишь написать код для взаимодействия с пользователем. В функции main() мы определяем основной цикл программы для чтения введенных данных и расчета математических выражений, введенных пользователем:
Проверим результат нашей работы:
Заключение
Итак, вы можете использовать eval() для выполнения выражений Python из строкового или кодового ввода. Эта встроенная функция полезна, когда вы пытаетесь динамически обновлять выражения Python и хотите избежать проблем с созданием собственного обработчика выражений. Однако пользоваться ей стоит с осторожностью.
Другие наши недавние статьи с подробным разбором различных аспектов стандартной библиотеки Python:




