5 Easy Ways to Use ast.literal_eval() and its Functions

We often need a way to evaluate certain Python expressions inside our python code without getting into much trouble with malicious expressions. We can use ast.literal_eval() in our python code to achieve those things.
What is ast.literal_eval()?
“ast” class’ full form is Abstract Syntax Tree. It contains ast.literal_eval() function. It is used to evaluate trees of the Python abstract syntax grammar. Abstract syntax changes with each python release. Custom parsers are one use case of ast.literal_eval() function.
ast.literal_eval() acceptable parameters
We use the ast.literal_eval() to securely evaluate a Python string containing a literal or container display.
Only the following Python literal structures are permissible in the string passed to the ast.lietral_eval() such as:-
- Strings.
- Tuples.
- Dictionaries.
- Sets
- Lists
- Booleans
- Bytes
- Numbers
- None
We can only pass a string as an argument to ast.literal_eval() containing expression.
Its syntax is as follows:-
Why use ast.literal_eval()
Without us having to put effort into interpreting the contents, the ast.literal eval function securely evaluates strings containing Python values from malicious sources.
However, this function cannot evaluate complicated expressions including indexing or operators.
It throws an error if the input is not one of the known data types, as we saw above.
Some examples
There are various examples of how to use ast.literal_eval().
Let us see some examples:
In this example, we will be converting the string representation of a list into a list using ast.literal_eval():-
The above code will have output as:-
![It shows the output as a list of strings [a,b,c,d] and type as a list.](https://www.pythonpool.com/wp-content/uploads/2022/12/output-1.png)
We often compare eval() and ast.literal_eval(). They are not completely identical, even though they appear to do the same things as each other.
The ast.literal_eval() takes a bit more precaution and safeguards against any mishappening which can happen upon evaluating a python expression.
Let us see an example to understand better what I am talking about:-
The Ast.literal eval() will produce an error if you pass it
yet eval() will cheerfully erase your files.
Use ast.literal eval because it appears you only allow the user to enter a normal dictionary ().
The eval evaluates any expression and will begin deleting the files as soon as we implement the above expression. The ast.literal_eval() completes the above request without any headache.
The reason behind the restricted use of ast.literal_eval()
ast.literal_eval() function can act as a viable substitute for eval() since it is safe as compared to eval().
Additionally, parsing more complex expressions like multiplication, list/dictionary indexing, and function calls are ineffective due to the safety mechanisms built into the language.
Safety comes at a cost.
Python’s eval() vs ast.literal_eval()
Here we will be comparing python’s eval() and ast.literal_eval()
| eval() | literal_eval() |
|---|---|
| It doesn’t have any restrictions. | It only accepts a portion of Python’s syntax as legitimate |
| It evaluates the code as soon as the function is called; we will have to evaluate its safety by ourselves. | If the input is not a valid Python datatype, an exception is thrown, and the function is not performed. |
| It is really powerful, but it can be quite hazardous if we allow strings to be evaluated from untrusted input. | Safely evaluate an expression node or a string containing a Python literal or container display. |
| Syntax:- eval(expression) | Syntax:- ast.literal_eval(node_or_string) |
Comparison table between eval() and ast.literal_eval()
What is its alternative?
The eval() is one of its alternatives, but it is not recommended as it is very powerful and can be dangerous.
The ast.parse() is another of its alternative, which can take a string as its input, parses, and then evaluates.
What does malformed string mean?
The error “malformed string” occurs when the string passed for evaluation is incomprehensible.
E.g., the below snippet will produce an error, namely “malformed string”, as we have forgotten to represent a,b,c, and as separate strings.
The following code corrects the above problem:-
Using ast.literal_eval() with pandas
Using AST’s literal_eval() function, we can handle more complex kinds of data in which a specific column may include an array of values rather than standard data types such as Strings, Integers, Timestamps, and so on.
ast.literal_eval() vs json.loads()
The json.loads() function parses a valid JSON string. It converts it to a Python dictionary. ast.literal_eval evaluates legitimate python expressions. ast.literal_eval() will work in the places where json.loads() won’t work.
ast.literal_eval() unexpected EOF while parsing
ast uses compile to convert the source string (which must be an expression) into an AST. If the source string is not a valid expression (for example, an empty string), compile will throw a SyntaxError “unexpected EOF while parsing”.
The below code throws a syntax error
Compilers frequently employ binary trees to create an interim visualization of the code that has not been completely compiled, known as an abstract syntax tree.
Yes, they can be called data structures; they are widely used in compilers.
Using python's eval() vs. ast.literal_eval()
I have a situation with some code where eval() came up as a possible solution. Now I have never had to use eval() before but, I have come across plenty of information about the potential danger it can cause. That said, I’m very wary about using it.
My situation is that I have input being given by a user:
Where datamap needs to be a dictionary. I searched around and found that eval() could work this out. I thought that I might be able to check the type of the input before trying to use the data and that would be a viable security precaution.
I read through the docs and I am still unclear if this would be safe or not. Does eval evaluate the data as soon as its entered or after the datamap variable is called?
Is the ast module’s .literal_eval() the only safe option?
![]()
![]()
6 Answers 6
datamap = eval(input(‘Provide some data here: ‘)) means that you actually evaluate the code before you deem it to be unsafe or not. It evaluates the code as soon as the function is called. See also the dangers of eval .
ast.literal_eval raises an exception if the input isn’t a valid Python datatype, so the code won’t be executed if it’s not.
Use ast.literal_eval whenever you need eval . You shouldn’t usually evaluate literal Python statements.
![]()
ast.literal_eval() only considers a small subset of Python’s syntax to be valid:
The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, and None .
Passing __import__(‘os’).system(‘rm -rf /a-path-you-really-care-about’) into ast.literal_eval() will raise an error, but eval() will happily delete your files.
Since it looks like you’re only letting the user input a plain dictionary, use ast.literal_eval() . It safely does what you want and nothing more.
eval: This is very powerful, but is also very dangerous if you accept strings to evaluate from untrusted input. Suppose the string being evaluated is «os.system(‘rm -rf /’)» ? It will really start deleting all the files on your computer.
ast.literal_eval: Safely evaluate an expression node or a string containing a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, None, bytes and sets.
Syntax:
Example:
In the above code ().__class__.__bases__[0] nothing but object itself. Now we instantiated all the subclasses, here our main enter code here objective is to find one class named n from it.
We need to code object and function object from instantiated subclasses. This is an alternative way from CPython to access subclasses of object and attach the system.
From python 3.7 ast.literal_eval() is now stricter. Addition and subtraction of arbitrary numbers are no longer allowed. link
Python’s eager in its evaluation, so eval(input(. )) (Python 3) will evaluate the user’s input as soon as it hits the eval , regardless of what you do with the data afterwards. Therefore, this is not safe, especially when you eval user input.
As an example, entering this at the prompt could be very bad for you:
In recent Python3 ast.literal_eval() "no longer parses simple strings"*, instead you are supposed to use the ast.parse() method to create an AST then interpret it.
* UPDATE (Q1:2023): I sometimes get comments about the meaning of «simple strings» in this context. On reading up on the current status I’ve added this update to try and addresses that.
I wrote this answer some time ago and I used the "simple string" phrase from my reference at the time, sadly I don’t recall the source but it was probably getting outdated, but it is true that at one time this method expected something other than a string. So at the time this was a reference to Python 2 and that fact changed slightly in Python 3, but it does come with limitations. Then at some point I updated the code presented from Py2 to Py3 syntax, causing the confusion.
I hope this answer is still a complete example of how to write a safe parser that can evaluate arbitrary expressions under the control of the author that can then be used to interpret uncontrolled data by sanitising each parameter. Comments appreciated as I still use something similar in live projects!
ast — Абстрактные синтаксические деревья¶
Модуль ast помогает Python приложениям обрабатывать Python деревья абстрактных синтаксических грамматик. Сам абстрактный синтаксис может измениться с каждым выпуском Python’а; этот модуль помогает программно узнать, как выглядит текущая грамматика.
Абстрактное синтаксическое дерево может быть создано путём передачи ast.PyCF_ONLY_AST как флаг встроенной функции compile() или с использованием parse() хелпера, представленного в этом модуле. Результатом будет дерево объектов, чьи классы наследуются от ast.AST . Абстрактное синтаксическое дерево может быть скомпилировано в объект Python кода с помощью встроенной функции compile() .
Node классы¶
Является базовым для всех классов AST нод. Фактические нод классы извлекаются из файла Parser/Python.asdl , которые воспроизводятся ниже . Они определены в C модуле _ast и реэкспортируются в ast .
В абстрактной грамматике (например, класс или ast.expr ) для каждого левого символа определен один ast.stmt . Кроме того, для каждого конструктора справа определен один класс; данные классы наследуются от классов для левосторонних деревьев. Например, ast.BinOp наследуется от ast.expr . Для производственных правил с альтернативами (например, «суммами») левосторонний класс абстрактен: всегда создаются только экземпляры определенных нод конструктора.
_fields ¶
Каждый класс содержит атрибут _fields предоставляющий имена всех дочерних узлов.
- Если существуют позиционные аргументы, их должно быть столько, сколько элементов в T._fields ; они будут назначены в качестве атрибутов этих имён.
- Если есть ключевые аргументы, они зададут атрибуты одних и тех же имён для заданных значений.
или более компактно:
Изменено в версии 3.8: Класс ast.Constant теперь используемый для всех констант.
Не рекомендуется, начиная с версии 3.8: Старые классы ast.Num , ast.Str , ast.Bytes , ast.NameConstant и ast.Ellipsis по-прежнему доступны, но будут удалены в будущих Python релизах. Тем временем, создание их экземпляров вернёт сущность другого класса.
Абстрактная грамматика¶
Абстрактная грамматика в настоящее время определяется следующим образом:
Помощники ast ¶
Кроме нод классов, модуль ast определяет служебные функции и классы для обхода абстрактных синтаксических деревьев:
ast. parse ( source, filename='<unknown>’, mode=’exec’, *, type_comments=False, feature_version=None ) ¶
Выполнит синтаксический анализ источника в AST ноде. Эквивалентно compile(source, filename, mode, ast.PyCF_ONLY_AST) .
Если указано type_comments=True , парсер изменяется для проверки и возврата типа комментариев, как указано в PEP 484 и PEP 526. Это эквивалентно добавлению ast.PyCF_TYPE_COMMENTS к флагам, переданным compile() . При этом будут сообщены синтаксические ошибки для недопустимых типов комментариев. Без этого флага комментарии типа будут игнорироваться и поле type_comment на выбранных AST нодах будет всегда None . Кроме того, расположение # type: ignore комментариев будет возвращено как атрибут type_ignores Module (в противном случае это всегда пустой список).
Кроме того, если mode является ‘func_type’ , входной синтаксис модифицируется таким образом, чтобы он соответствовал PEP 484 «сигнатурой типа комментариев», например (str, int) -> List[str] .
Кроме того, при установке feature_version в (major, minor) кортежа будет предпринята попытка синтаксического анализа с использованием грамматики заданной версии Python. В настоящее время major должно быть равно 3 . Например, установка feature_version=(3, 4) позволит использовать async и await в качестве имён переменных. Самая низкая поддерживаемая версия — (3, 4) ; самая высокая — sys.version_info[0:2] .
Предупреждение
Возможно крушение Python интерпретатора с большой/сложной строкой из-за ограничений глубины стека Python компилятора AST.
Изменено в версии 3.8: Добавлены type_comments , mode=’func_type’ и feature_version .
Безопасное вычисление узла выражения или строки, содержащей Python литерал или отображение контейнера. Предоставленная строка или узел может состоять только из следующих Python литеральных структур: строки, байты, числа, кортежи, списки, словари, множества, були и None .
Это может использоваться для безопасного вычисления строки, содержащей Python значения из ненадежных источников без необходимости разбора самих значений. Она не способна вычислять произвольно сложные выражения, например, с участием операторов или индексирования.
Предупреждение
Возможно крушение Python интерпретатора с большой/сложной строкой из-за ограничений глубины стека Python компилятора AST.
Изменено в версии 3.2: Теперь разрешены байты и установка литералов.
Возвращает докстринг для переданного node (которая должна быть нодой FunctionDef , AsyncFunctionDef , ClassDef или Module ) или None , если у ней нет докстринга. Если clean истинно, то очищается отступ докстринга с помощью inspect.cleandoc() .
Изменено в версии 3.5: Теперь поддерживается AsyncFunctionDef .
Получение сегмента исходного кода source, создавшего node. Если какая-либо информация о местоположении ( lineno , end_lineno , col_offset или end_col_offset ) отсутствует, вернётся None .
Если padded — True , первая строка многострочного оператора будет заполнена пробелами в соответствии с исходным положением.
Добавлено в версии 3.8.
При компиляции дерева нод с помощью compile() компилятор ожидает lineno и col_offset атрибутов для каждой поддерживаемой ноды. Это довольно утомительно для заполнения созданных нод, поэтому хелпер рекурсивно добавляет атрибуты там, где они ещё не установлены, путем установки их значениями родительской ноды. Она работает рекурсивно, начиная с node.
ast. increment_lineno ( node, n=1 ) ¶
Увеличивает номер строки и номер конечной строки каждой ноды дерева, начиная с node до n. Она полезна для «перемещения кода» в другое расположение в файле.
ast. copy_location ( new_node, old_node ) ¶
Копирует исходное местоположение ( lineno , col_offset , end_lineno и end_col_offset ) из old_node в new_node, если возможно, возвращает new_node.
ast. iter_fields ( node ) ¶
Отдаёт кортеж (fieldname, value) для каждого поля в node._fields , который присутствует в ноде.
ast. iter_child_nodes ( node ) ¶
Отдаёт все прямые дочерние узлы node, то есть все поля, которые являются нодами и всех элементов полей, являющихся списками нод.
Рекурсивно отдаёт все дочерние ноды в дереве, начиная с node (включая саму node), в неопределенном порядке. Это полезно, если нужно изменить только ноды на месте и не беспокоиться о контексте.
class ast. NodeVisitor ¶
Базовый класс посетителя ноды, производящий обход абстрактного синтаксического дерева и вызывает функции посетителя для каждого найденного узла. Функция может возвращать передаваемое методу visit() значение.
Класс должен быть подклассом, а подкласс добавляет методы посетителю.
Посещает ноду. Реализация по умолчанию вызывает метод self.visit_ classname , где classname имя класса ноды или generic_visit() , если этот метод не существует.
Посетитель вызывает visit() на всех дочерних узлах.
Обратите внимание, что дочерние ноды нод с иным методом посетителя не будут посещаться, если только посетитель не вызовет generic_visit() или сам не посетит их.
Не используйте NodeVisitor , если требуется во время прохождения применить изменения к нодам. Для этого существует специальный посетитель ( NodeTransformer ), который допускает модификации.
Не рекомендуется, начиная с версии 3.8: Методы visit_Num() , visit_Str() , visit_Bytes() , visit_NameConstant() и visit_Ellipsis() теперь запрещены и не будут вызываться в будущих Python версиях. Добавлен метод visit_Constant() для обработки всех константных нод.
Подкласс NodeVisitor обходит абстрактное синтаксическое дерево и позволяет менять ноды.
NodeTransformer обходит AST и использовать возвращаемое значение методов посетителя для замены или удаления старых нод. Если возвращаемое значение метода посетителя является None , нода удаляется из его местоположения, в противном случае он заменяется возвращаемым значением. Возвращаемое значение может быть исходной, в этом случае замена не выполняется.
Далее приведён пример преобразователя, который перезаписывает все вхождения найденных имён ( foo ) в data[‘foo’] :
Помните, что если нода, над которой вы работаете, содержит дочерние ноды, необходимо либо преобразовать дочерние ноды самостоятельно, либо вызвать метод generic_visit() для этой ноды.
Для нод, которые были частью операторов коллекции (применимая ко всем операторам нод), посетитель может также вернуть список нод, а не только одну ноду.
Если NodeTransformer вводит новые ноды (которые не были частью исходного дерева) без предоставления им информации о местоположении (например, lineno ), fix_missing_locations() следует вызвать вместе с новым поддеревом для повторного расчёта информации о местоположении:
Обычно преобразователь используется следующим образом:
Возвращение отформатированного дампа дерева нод. Бывает полезно для отладки. Если annotate_fields содержит значение True (по умолчанию), в возвращаемой строке будут отображаться имена и значения полей. Если annotate_fields ложно, то строка результата будет более компактной, если не указать однозначные имена полей. По умолчанию такие атрибуты, как номера строк и смещения столбцов, не сбрасываются. Если это требуется, include_attributes можно установить значение в True.
Зеленые Древесные Змеи, внешний ресурс документации, содержащий хорошие сведения о работе с Python AST.
ASTTokens аннотирует Python AST с позициями токенов и текста в исходном коде, который их сгенерировал. Это полезно для инструментов, которые делают преобразования исходного кода.
leoAst.py объединяет представления программ python на основе токенов и дерева синтаксического анализа, вставляя двухсторонние связи между токенами и ast узлами.
LibCST анализирует код как синтаксическое дерево, которое выглядит как ast дерево и сохраняет все детали форматирования. Он полезен для создания приложений автоматизированного рефакторинга (codemod) и линтеров.
Parso — парсер Python, который поддерживает восстановление ошибок и синтаксический анализ туда и обратно для различных версий Python (в нескольких версиях Python). Parso также может перечислить несколько синтаксических ошибок в вашем python файле.
What is ast.literal_eval(node_or_string) in Python?
Many candidates are rejected or down-leveled due to poor performance in their System Design Interview. Stand out in System Design Interviews and get hired in 2023 with this popular free course.
Python ast module
The ast module (Abstract Syntax Tree) tree representation of source code allows us to interact with and modify Python code. Python comes with abstract syntax grammar that is subject to change with every Python release.
The ast module helps applications to process trees of syntax and find out what current syntax grammar looks like programmatically. Abstract syntax trees are great tools for program analysis and program transformation systems.
ast.literal_eval method
The ast.literal_eval method is one of the helper functions that helps traverse an abstract syntax tree. This function evaluates an expression node or a string consisting of a Python literal or container display.
The ast.literal_eval method can safely evaluate strings containing Python values from unknown sources without us having to parse the values. However, complex expressions involving indexing or operators cannot be evaluated using this function.
Parameters
node_or_string : The node or string that is to be evaluated. It may consist of the following Python literal structures: