Why does ast.literal_eval ('5 * 7') fail?

Why is a literal score of 5 * 7 performed, but 5 + 7 is not?

 import ast print(ast.literal_eval('5 + 7')) # -> 12 print(ast.literal_eval('5 * 7')) # -> Traceback (most recent call last): ... ValueError: malformed node or string: <_ast.BinOp object at ...> 

The documentation does not explain this.

I found this problem after answering this question in SO: Getting the result of a string .

+5
source share
2 answers

ast.literal_eval() accepts + in the evaluated data because 5+2j (complex number * ) are valid literals. The same goes for - . To keep the code simple, no attempt is made to exclude + or - as binary operators.

No other operators are allowed; a function should only accept literals, not expressions.

In other words, 5 + 7 is a mistake, but itโ€™s hard to solve without breaking support for constructing complex numbers. The implementation restricts the use of operands, which are numbers, unary + and - , or other binary operators (so you cannot use them to combine lists or make a difference in settings).

Also see several related Bugtracker entries in Python: # 25335 ast.literal_eval cannot parse numbers with leading "+" , # 22525 ast.literal_eval () does not execute documentation and # 4907 ast.literal_eval does not handle complex numbers correctly


* From a technical point of view, 2j is a valid literal; Python parses 5+2j as int(5) binop(+) complex(0, 2) and only later yields the complex(5, 2) object from the result when the addition was actually executed.

+10
source

The question is not why * not accepted, but rather, "why + accepted at all."

ast.literal_eval can parse literals, but not expressions. However, in Python, complex numbers are not expressed as a single literal value; instead, they consist of the real part and the imaginary part combined together; the imaginary part is signaled with j . literal_eval therefore needs to support binary + and - to support complex number constants such as 1 + 2j or -3.4e-5 - 1.72e9j .

In many versions, including Python 3.5, literal_eval much weaker than necessary, it accepts any chain of additions and subtractions until both left and right sides evaluate any number, thus (1 + 3) + 2 + (4 - 5) is still being analyzed, even if it is not a complex constant consisting of the real + imaginary part.


+ and - not accepted unconditionally: if you try to add 2 lists together, this will fail, even if it can parse list literals, and the addition is defined for lists:

 >>> ast.literal_eval('[1] + [2]') Traceback (most recent call last): ... ValueError: malformed node or string: <_ast.BinOp object at 0x7fdddbe785f8> >>> ast.literal_eval('[1, 2]') [1, 2] >>> [1] + [2] [1, 2] 
+4
source

Source: https://habr.com/ru/post/1259708/


All Articles