Question about ast.literal_eval

Chris Angelico rosuav at gmail.com
Mon May 20 03:38:18 EDT 2013


On Mon, May 20, 2013 at 5:05 PM, Frank Millman <frank at chagford.com> wrote:
> Hi all
>
> I am trying to emulate a SQL check constraint in Python. Quoting from the
> PostgreSQL docs, "A check constraint is the most generic constraint type. It
> allows you to specify that the value in a certain column must satisfy a
> Boolean (truth-value) expression."
>
> The problem is that I want to store the constraint as a string, and I was
> hoping to use ast.literal_eval to evaluate it, but it does not work.
>
>>>> x = 'abc'
>>>> x in ('abc', xyz')
> True
>>>> b = "x in ('abc', 'xyz')"
>>>> eval(b)
> True
>>>> from ast import literal_eval
>>>> literal_eval(b)
> ValueError: malformed node or string: <_ast.Compare object at ...>
>
> Is there a safe way to do what I want? I am using python 3.3.

An SQL constraint has a whole lot that Python can't do conveniently,
and vice versa, so I think you do yourself a disservice by trying to
tie yourself to that.

The problem here is that 'in' is an operator, so this is not a
literal. One possible solution would be to separate out your operator
(and have just a handful permitted), and then use ast.literal_eval for
just the second operand - something like this:

import ast
import operator
ops = {
  'in':lambda x,y: x in y,  # operator.contains has the args backwards
  '==':operator.eq, # or use '=' for more SQL-like syntax
  '<':operator.lt,
  '>':operator.gt,
}

op, value = 'in', "('abc', 'xyz')"
x = 'abc'

if ops[op](x,ast.literal_eval(value)):
  print("Constraint passed")
else:
  print("Ignore this one")

ChrisA



More information about the Python-list mailing list