Парсинг логических выражений python

Безопасный парсер выражений в Python

Как я могу позволить пользователям безопасно выполнять математические выражения? Нужно ли писать полный парсер? Есть ли что-то вроде ast.literal_eval(), но для выражений?

5 ответов

В странице примеров Pyparsing перечислены несколько парсеров выражений: http://pyparsing.wikispaces.com/file/view/fourFn.py — обычная реализация синтаксического анализа/оценки оценщика арифметических инфикс с использованием pyparsing (несмотря на свое имя, на самом деле это 5-функциональная арифметика, плюс несколько функций триггера) http://pyparsing.wikispaces.com/file/view/simpleBool.py — логический синтаксический анализатор/оценщик булевых инфикс, используя вспомогательный метод pyparsing operatorPrecedence , который упрощает определение инфиксного оператора нотации http://pyparsing.wikispaces.com/file/view/simpleArith.py http://pyparsing.wikispaces.com/file/view/eval_arith.py — Пара примеров, переработавших fourFn.py с помощью operatorPrecedence . Первый просто анализирует и возвращает дерево синтаксического анализа, второе добавляет логику оценки.

Какие выражения вы хотите? Переменное назначение? Оценка функции?

SymPy стремится стать полноценным CAS Python.

Я могу изменить свои потребности в зависимости от имеющихся возможностей. SymPy выглядит интересно. Небольшая однофайловая библиотека была бы еще лучше.

@ Иво: возможности зависят от ваших потребностей! @Paul связал несколько простых способов сделать это с pyparsing . SymPy дает больше энергии при больших SymPy (большой, может быть медленным).

Несколько недель назад я сделал аналогичную вещь, но для логических выражений (или, а, нет, сравнений, круглых скобок и т.д.). Я сделал это, используя парсер Ply. Я создал простой лексер и парсер. Parser создал дерево AST, которое позже использовалось для выполнения вычислений. Выполняя это, вы сможете полностью контролировать, что вводит пользователь, потому что будут анализироваться только выражения, совместимые с грамматикой.

Да. Даже если для выражений был эквивалент выражения ast.literal_eval() , выражение Python может быть большим, чем просто чистое математическое выражение, например, произвольный вызов функции.

Читайте также:  What is java certification

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

Функции maths состоят из числовых символов и символов пунктуации, возможно «E» или «e», если вы допускаете научную нотацию для рациональных чисел, и единственным (другим) легальным использованием альфа-символов будет, если вы разрешаете/предоставляете конкретные математические данные функций (например, stddev). Итак, должно быть тривиально бегать по строке для альфа-символов и проверять следующий маленький бит не является подозрительным, а затем просто вычислять строку в блоке try/except.

def evalMaths(s): i = 0 while i < len(s): while s[i].isalpha() and i < len(s): idn += s[i] i += 1 if (idn and idn != 'e' and idn != 'abs' and idn != 'round'): raise Exception("you naughty boy: don't " + repr(idn)) else: i += 1 return eval(s) 

Мне было бы очень интересно узнать, как и как его можно обойти. (^_^) BTW/Я знаю, что вы можете вызывать функции, такие как abs2783 или _983, - если они существуют, но они не будут. Я имею в виду что-то практическое.

На самом деле, если кто-то может это сделать, я создам вопрос с 200 щедростью и приму их ответ.

-1 Не делай этого. eval -ный пользователя входной строки никогда не является хорошей идеей. Кто-то найдет способ обойти вашу защиту.

Как насчет обоснования, а не абсолютно бессмысленного утверждения? Это может быть не очень красиво, но если вы хотите что-то сделать, есть анализ затрат и выгод, когда у вас нет работающего решения, или возитесь с чем-то более сложным.

Я с Тони на этот раз. Инженерия - это понимание затрат и выгод. Правда, использование eval сопряжено с огромным риском, но есть ситуации, когда это уместно. У меня есть командная строка eval.py, которую я использую для быстрых вычислений. Я пользователь, так что использование eval прекрасно. Вы должны знать, что вы делаете, но «никогда» - это сильное слово.

@Ned: правда это. Я думал «ненадежный пользователь», и в этом случае я бы все равно сказал «никогда».

@Tony: если s не является строкой: pastebin.com/tennNUx2 . Если это так, вы можете вызвать ошибку с помощью 'round(round)' ; в противном случае я все еще думаю!

@Ned: хороший момент. Тем не менее, здесь явно задан вопрос о чем-то доказательстве злоупотреблений. @Alex: round (round) в порядке - я всегда говорил, чтобы это вызывалось в блоке try / кроме. Другие интересны: eval в строке '"()" * 8 ** 5' безопасен, и это то, что может использовать пользователь. Но eval с очень длинной строкой может дать сбой . если пользователь выполняет чтение без какого-либо ограничения на размер, то всегда есть уязвимость, хотя и не существующая, совершенно независимая от использования eval. Итак, согласитесь ли вы, что это отдельная проблема ввода / вывода, а не проблема?

Ещё вопросы

  • 1 Объяснение о клоне необходим массив, содержащий клонируемые объекты
  • 1 Алгоритм самой длинной палиндромной последовательности, анализ времени
  • 0 JQuery Невозможно получить данные службы drupal через localhost: 8888
  • 0 Почему этот код печатает 0
  • 0 Независимые куки в разных папках
  • 0 MySQL, как найти общие данные в нескольких таблицах
  • 0 AngularJS -Контроллер не вызывается
  • 1 Как получить первый элемент результата базы данных FIrebase в Python?
  • 0 Как отобразить jquery querySelect или выбранный файл?
  • 0 MySQL: mysqli_fetch_array ()
  • 0 Поворот 3D камеры с помощью DirectX11
  • 1 OAuth Google Plus войдите в систему: 400. Это ошибка. Ошибка: redirect_uri_mismatch
  • 1 Knockout-привязка данных в функции
  • 0 Вернуть n-ю строку
  • 1 ngModel не может правильно определить изменения массива
  • 0 Дизайн синхронизации потоков Qt
  • 0 Как реализовать стек с помощью std :: vector?
  • 0 Как сделать копии (новые экземпляры) функции замыкания?
  • 0 Шаблон Joomla 3 - ширина модуля в обертке
  • 0 PHP пока петли в то время как петли не работают
  • 1 Элемент xmpmeta здесь не разрешен, когда я импортирую файл SVG
  • 0 Создать сводную таблицу на основе двухколоночного SQL-запроса в PHP
  • 0 Добавление пользовательских атрибутов в шаблон ejs
  • 0 Не могу получить подготовленное заявление для печати в php
  • 0 почему элемент указателя инициализирован ненулевым?
  • 1 Удалить похожие элементы из списка
  • 0 Принятие значений динамически создаваемых текстовых полей ввода HTML в C #
  • 0 Как зациклить анимацию в jQuery
  • 0 JQuery AutoCompleter - мульти и пользовательские данные
  • 0 проверьте руководство, соответствующее вашей версии сервера MariaDB, на предмет правильного синтаксиса для использования рядом с 'WHERE \ r \ n
  • 1 Как получить XML-контент в виде строки
  • 1 Передача более одного значения из списка DropDown
  • 0 Как прочитать значения динамической HTML-таблицы из текстового файла?
  • 1 Я хочу нарисовать квадрат на картинке C #
  • 0 Угловое изменение ввода текстового поля JS - Смотреть
  • 0 Передача массива из JQuery в PHP через POST
  • 0 Нужно ли закрывать соединение с пулом для каждого API в nodejs + mysql?
  • 0 Угловой дизайн материала md-autocomplete с md-max-length и рисунком
  • 1 Python re.findall возвращает только первый символ
  • 1 Установка переменных среды в WinDbg
  • 0 как получить необходимый контент, используя функцию strip_tags в php
  • 0 Приведение / разыменование указателей на символы в двойной массив
  • 1 перераспределить данные в гауссовом распределении с помощью pd.DataFrame
  • 0 PHP строка для разделения массива
  • 1 Числовое нечеткое сравнение Присоединение к Python / pandas dataframes
  • 0 Hover FadeOut для определенного класса
  • 1 ValueError: недопустимый литерал для int () с основанием 10: '' при запросе ввода
  • 1 Есть ли способ получения информации, отображаемой в работающем приложении Android?
  • 0 SQL Server против MySQL
  • 1 Передать данные в pug с помощью pug-html-loader (не может прочитать свойство undefined)

Источник

Parsing A Boolean Expression in Python

Suppose we have a boolean expression, we have to find the result after evaluating that expression.

An expression can either be −

  • "t", evaluating to True;
  • "f", evaluating to False;
  • "!(expression)", evaluating to the logical NOT of the inner expression;
  • "&(expr1,expr2. )", evaluating to the logical AND of 2 or more inner expressions;
  • "|(expr1,expr2. )", evaluating to the logical OR of 2 or more inner expressions;

So, if the input is like "|(!(t),&(t,f,t))", then the output will be fasle, this is because !(t) is false, then &(t,f,t) is also false, so the OR of all false values will be false.

To solve this, we will follow these steps −

  • define solve(), this will take e, i
  • if e[i] is same as "f", then −
    • return (False, i + 1)
    • if e[i] is same as ",", then −
      • i := i + 1
      • Ignore following part, skip to the next iteration
      • return true when all elements are true in stack, otherwise false, i + 1
      • return true when at least one elements is true in stack, otherwise false, i + 1

      Let us see the following implementation to get better understanding −

      Example

      class Solution(object): def parseBoolExpr(self, expression): s,y = self.solve(expression,0) return s def solve(self,e,i): if e[i] =="f": return False,i+1 elif e[i] == "t": return True,i+1 op = e[i] i = i+2 stack = [] while e[i]!=")": if e[i] == ",": i+=1 continue res,i = self.solve(e,i) stack.append(res) if op == "&": return all(stack),i+1 elif op == "|": return any(stack),i+1 return not stack[0],i+1 ob = Solution() print(ob.parseBoolExpr("|(!(t),&(t,f,t))"))

      Источник

      Python: парсинг логической строки в список списков

      Я получаю строку логических выражений из базы данных, и мне нужно поместить их в список списков для дальнейшей оценки. Я уже много читал о разборе строк, но пока не смог найти ответ. Для облегчения понимания проблемы, вот 3 примера:

      input_string1 = '((A OR B) AND (C OR D)) OR E' input_string2 = '(A AND ( B OR C ) AND D AND E)' input_string3 = ' A OR ( B AND C ) OR D OR E' 
      Results_string1=[ ['A', 'C'], ['A','D'], ['B','C'], ['B','D'], ['E']] Results_string2=[ ['A', 'B', 'D', 'E'], ['A', 'C', 'D', 'E'] ] Results_string3=[ ['A'], ['B','C'], ['D'], ['E'] ] 

      Так что в основном мне нужны полностью факторизованные выражения в терминах OR и помещать их в список. Это означает, что любое условие AND выражается наличием обоих выражений в одном и том же sublist , тогда как любое условие OR запускает создание новых подсписков.

      e.g. E AND F --> [E, F], E OR F --> [[E],[F]] 

      Строки из базы данных имеют произвольную длину и произвольное количество скобок.

      У любого есть идея, как определить грамматику, чтобы я мог использовать, например, пакет pyparsing?

      import pyparsing as pp gene_id = pp.Word(pp.alphanums) logical = ( pp.Keyword("AND") | pp.Keyword("OR") ).setName("logical") l_brackets = (pp.Literal('(') ).setName('l_brackets') r_brackets = ( pp.Literal(')') ).setName('r_brackets') 

      Но как мне определить настоящий парсер?

      Одна из основных проблем заключается в том, что я не знаю, как обрабатывать произвольные скобки и длину строки. Я играл с nestedExpr()-parser из набора инструментов pyparser , но пока не смог создать правильное поведение.

      Источник

Оцените статью