[python] Malformed String ValueError ast.literal_eval() with String representation of Tuple

I'm trying to read in a string representation of a Tuple from a file, and add the tuple to a list. Here's the relevant code.

raw_data = userfile.read().split('\n')
for a in raw_data : 
    print a
    btc_history.append(ast.literal_eval(a))

Here is the output:

(Decimal('11.66985'), Decimal('0E-8'))
Traceback (most recent call last):


File "./goxnotify.py", line 74, in <module>
    main()
  File "./goxnotify.py", line 68, in main
    local.load_user_file(username,btc_history)
  File "/home/unix-dude/Code/GoxNotify/local_functions.py", line 53, in load_user_file
    btc_history.append(ast.literal_eval(a))
  File "/usr/lib/python2.7/ast.py", line 80, in literal_eval
    return _convert(node_or_string)

  `File "/usr/lib/python2.7/ast.py", line 58, in _convert
   return tuple(map(_convert, node.elts))
  File "/usr/lib/python2.7/ast.py", line 79, in _convert
   raise ValueError('malformed string')
   ValueError: malformed string

The answer is


Use eval() instead of ast.literal_eval() if the input is trusted (which it is in your case).

raw_data = userfile.read().split('\n')
for a in raw_data : 
    print a
    btc_history.append(eval(a))

This works for me in Python 3.6.0


I know this is an old question, but I think found a very simple answer, in case anybody needs it.

If you put string quotes inside your string ("'hello'"), ast_literaleval() will understand it perfectly.

You can use a simple function:

    def doubleStringify(a):
        b = "\'" + a + "\'"
        return b

Or probably more suitable for this example:

    def perfectEval(anonstring):
        try:
            ev = ast.literal_eval(anonstring)
            return ev
        except ValueError:
            corrected = "\'" + anonstring + "\'"
            ev = ast.literal_eval(corrected)
            return ev

ast.literal_eval (located in ast.py) parses the tree with ast.parse first, then it evaluates the code with quite an ugly recursive function, interpreting the parse tree elements and replacing them with their literal equivalents. Unfortunately the code is not at all expandable, so to add Decimal to the code you need to copy all the code and start over.

For a slightly easier approach, you can use ast.parse module to parse the expression, and then the ast.NodeVisitor or ast.NodeTransformer to ensure that there is no unwanted syntax or unwanted variable accesses. Then compile with compile and eval to get the result.

The code is a bit different from literal_eval in that this code actually uses eval, but in my opinion is simpler to understand and one does not need to dig too deep into AST trees. It specifically only allows some syntax, explicitly forbidding for example lambdas, attribute accesses (foo.__dict__ is very evil), or accesses to any names that are not deemed safe. It parses your expression fine, and as an extra I also added Num (float and integer), list and dictionary literals.

Also, works the same on 2.7 and 3.3

import ast
import decimal

source = "(Decimal('11.66985'), Decimal('1e-8'),"\
    "(1,), (1,2,3), 1.2, [1,2,3], {1:2})"

tree = ast.parse(source, mode='eval')

# using the NodeTransformer, you can also modify the nodes in the tree,
# however in this example NodeVisitor could do as we are raising exceptions
# only.
class Transformer(ast.NodeTransformer):
    ALLOWED_NAMES = set(['Decimal', 'None', 'False', 'True'])
    ALLOWED_NODE_TYPES = set([
        'Expression', # a top node for an expression
        'Tuple',      # makes a tuple
        'Call',       # a function call (hint, Decimal())
        'Name',       # an identifier...
        'Load',       # loads a value of a variable with given identifier
        'Str',        # a string literal

        'Num',        # allow numbers too
        'List',       # and list literals
        'Dict',       # and dicts...
    ])

    def visit_Name(self, node):
        if not node.id in self.ALLOWED_NAMES:
            raise RuntimeError("Name access to %s is not allowed" % node.id)

        # traverse to child nodes
        return self.generic_visit(node)

    def generic_visit(self, node):
        nodetype = type(node).__name__
        if nodetype not in self.ALLOWED_NODE_TYPES:
            raise RuntimeError("Invalid expression: %s not allowed" % nodetype)

        return ast.NodeTransformer.generic_visit(self, node)


transformer = Transformer()

# raises RuntimeError on invalid code
transformer.visit(tree)

# compile the ast into a code object
clause = compile(tree, '<AST>', 'eval')

# make the globals contain only the Decimal class,
# and eval the compiled object
result = eval(clause, dict(Decimal=decimal.Decimal))

print(result)

From the documentation for ast.literal_eval():

Safely evaluate an expression node or a string containing a Python expression. The string or node provided may only consist of the following Python literal structures: strings, numbers, tuples, lists, dicts, booleans, and None.

Decimal isn't on the list of things allowed by ast.literal_eval().


Examples related to python

programming a servo thru a barometer Is there a way to view two blocks of code from the same file simultaneously in Sublime Text? python variable NameError Why my regexp for hyphenated words doesn't work? Comparing a variable with a string python not working when redirecting from bash script is it possible to add colors to python output? Get Public URL for File - Google Cloud Storage - App Engine (Python) Real time face detection OpenCV, Python xlrd.biffh.XLRDError: Excel xlsx file; not supported Could not load dynamic library 'cudart64_101.dll' on tensorflow CPU-only installation

Examples related to parsing

Got a NumberFormatException while trying to parse a text file for objects Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse (<anonymous>) Python/Json:Expecting property name enclosed in double quotes Correctly Parsing JSON in Swift 3 How to get response as String using retrofit without using GSON or any other library in android UIButton action in table view cell "Expected BEGIN_OBJECT but was STRING at line 1 column 1" How to convert an XML file to nice pandas dataframe? How to extract multiple JSON objects from one file? How to sum digits of an integer in java?

Examples related to python-2.x

Combine several images horizontally with Python How to print variables without spaces between values How to return dictionary keys as a list in Python? How to add an element to the beginning of an OrderedDict? How to read a CSV file from a URL with Python? Malformed String ValueError ast.literal_eval() with String representation of Tuple Relative imports for the billionth time How do you use subprocess.check_output() in Python? write() versus writelines() and concatenated strings How to select a directory and store the location using tkinter in Python

Examples related to abstract-syntax-tree

Using python's eval() vs. ast.literal_eval()? Malformed String ValueError ast.literal_eval() with String representation of Tuple

Examples related to representation

Malformed String ValueError ast.literal_eval() with String representation of Tuple Fixed point vs Floating point number How to print (using cout) a number in binary form? Display the binary representation of a number in C?