# How is correct use of eval()

Hrvoje Niksic hniksic at xemacs.org
Tue Oct 12 18:28:09 CEST 2010

```Nobody <nobody at nowhere.com> writes:

> Oh, look what's "new in version 2.6":
>
> 	> ast.literal_eval("7")
> 	7
> 	> ast.literal_eval("7") == 7
> 	True

Note that it doesn't work for some reasonable inputs involving unary and
binary plus, such as "[-2, +1]" or "2+3j".  This has been fixed in the
development (3.2) sources.

An interesting aspect of ast.literal_eval is that it merely uses the
public API to access the AST provided by the compiler.  One is therefore
free to "fix" literal_eval in 2.6 or 2.7 by defining their own similar
function with the desired flavor.  For example:

import ast
from itertools import imap, izip

def my_literal_eval(s):
node = ast.parse(s, mode='eval').body
return _convert(node)

_safe_names = {'None': None, 'True': True, 'False': False}
_safe_operands = (ast.Num, ast.UnaryOp, ast.BinOp)
_safe_unops = (ast.UAdd, ast.USub)
_safe_binops = (ast.Add, ast.Sub)

def _convert(node):
if isinstance(node, ast.Str):
return node.s
elif isinstance(node, ast.Num):
return node.n
elif isinstance(node, ast.Tuple):
return tuple(imap(_convert, node.elts))
elif isinstance(node, ast.List):
return list(imap(_convert, node.elts))
elif isinstance(node, ast.Dict):
return dict((_convert(k), _convert(v)) for k, v
in izip(node.keys, node.values))
elif isinstance(node, ast.Name) and node.id in _safe_names:
return _safe_names[node.id]
elif isinstance(node, ast.UnaryOp) and \
isinstance(node.op, _safe_unops) and \
isinstance(node.operand, _safe_operands):
operand = _convert(node.operand)
return + operand
else:
return - operand
elif isinstance(node, ast.BinOp) and isinstance(node.op, _safe_binops) \
and isinstance(node.right, _safe_operands) \
and isinstance(node.left, _safe_operands):
left = _convert(node.left)
right = _convert(node.right)