I want to build a Keras Model evaluating strings. If I do the following:
from keras.models import Sequential
from keras.layers import Dense
model = Sequential()
model.add(Dense(units=10, input_shape=(10,), activation='softmax'))
It works fine. And I can see the model.summary().
But, when I add the layer with ast.literal_eval()
from keras.models import Sequential
from keras.layers import Dense
import ast
model = Sequential()
code = "model.add( Dense( input_shape=(10,), units=10, activation='softmax' ) )"
ast.literal_eval(code)
It throws me the next ValueError:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/ast.py", line 84, in literal_eval
    return _convert(node_or_string)
  File "/usr/lib/python3.5/ast.py", line 83, in _convert
    raise ValueError('malformed node or string: ' + repr(node))
ValueError: malformed node or string: <_ast.Call object at 0x7efc40c90e10>
If I use eval instead of ast.literal_eval it works too.
I'm using python3.5.
ast. literal_eval() The ast module helps Python applications to process trees of the Python abstract syntax grammar. The literal_eval safely evaluate an expression node or a string containing a Python literal or container display.
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.
If you see this error, it usually means the the client is not able to transform the string you wrote to the character set acceptable to the Firebird server. Here's a short explanation how this works: In your client program, you type in some text, which is then shown on the screen.
A big mistake: literal_eval only works for literals. In this case, I have a Call.
The function literal_eval first parse the string.
From /usr/lib/python3.5/ast.py: lines 38-46
def literal_eval(node_or_string):
    """
    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, bytes, numbers, tuples, lists, dicts,
    sets, booleans, and None.
    """
    if isinstance(node_or_string, str):
        node_or_string = parse(node_or_string, mode='eval')
At this point, node_or_string is an instance of Expression. Then, literal_eval get the body.
From /usr/lib/python3.5/ast.py: lines 47-48
    if isinstance(node_or_string, Expression):
        node_or_string = node_or_string.body
And finally, literal_eval checks the type of the body (node_or_string).
From /usr/lib/python3.5/ast.py: lines 49-84
    def _convert(node):
        if isinstance(node, (Str, Bytes)):
            return node.s
        elif isinstance(node, Num):
            return node.n
        elif isinstance(node, Tuple):
            return tuple(map(_convert, node.elts))
        elif isinstance(node, List):
            return list(map(_convert, node.elts))
        elif isinstance(node, Set):
            return set(map(_convert, node.elts))
        elif isinstance(node, Dict):
            return dict((_convert(k), _convert(v)) for k, v
                        in zip(node.keys, node.values))
        elif isinstance(node, NameConstant):
            return node.value
        elif isinstance(node, UnaryOp) and \
             isinstance(node.op, (UAdd, USub)) and \
             isinstance(node.operand, (Num, UnaryOp, BinOp)):
            operand = _convert(node.operand)
            if isinstance(node.op, UAdd):
                return + operand
            else:
                return - operand
        elif isinstance(node, BinOp) and \
             isinstance(node.op, (Add, Sub)) and \
             isinstance(node.right, (Num, UnaryOp, BinOp)) and \
             isinstance(node.left, (Num, UnaryOp, BinOp)):
            left = _convert(node.left)
            right = _convert(node.right)
            if isinstance(node.op, Add):
                return left + right
            else:
                return left - right
        raise ValueError('malformed node or string: ' + repr(node))
    return _convert(node_or_string)
If the initial code was ast.literal_eval('1+1') (for example), now node_or_string would be an instance of BinOp. But in the case of:
code = "model.add( Dense( input_shape=(10,), units=10, activation='softmax' ) )"
ast.literal_eval(code)
The body will be an instance of Call, which does not appear among the valid types of the function.
E.g.:
import ast
code_nocall = "1+1"
node = ast.parse(code_nocall, mode='eval')
body = node.body
print(type(body)) # Returns <class '_ast.BinOp'>
code_call = "print('hello')"
node = ast.parse(code_call, mode='eval')
body = node.body
print(type(body)) # Returns <class '_ast.Call'>
The best solution I have found so far, to not use eval directly, is to perform the process manually. With this function:
import ast
def eval_code(code):
    parsed = ast.parse(code, mode='eval')
    fixed = ast.fix_missing_locations(parsed)
    compiled = compile(fixed, '<string>', 'eval')
    eval(compiled)
Now it works:
eval_code("print('hello world')")
from keras.models import Sequential
from keras.layers import Dense
model = Sequential()
code = "model.add( Dense( input_shape=(10,), units=10, activation='softmax' ) )"
eval_code(code)
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With