Check if a string can be evaluated (with eval ()) in Python

I know I can try other than eval

myself, but I want to use it in list_comprehensions, or map

:

[eval(x) if isevaluable(x) else x for x in some_list]

      

My driving for this: I am getting an argument from sys.argv - which can be int \ float \ built-in-constants (especially True, False, None). I want to make them all in a simple and clean way.

[Note: secure evaluation is not an issue here (even this is really recommended)]

+3


source to share


2 answers


Obvious solution that may or may not work for your particular eval line.

def isevaluable(s):
    try:
        compile(s, "bogusfile.py", "exec")
        return True
    except:
        return False

      

This compiles the code, checking for syntax errors, etc. Not catching all your logic problems, but it will check for programming problems before shooting it to eval, which can cause all sorts of problems.

I thought of doing:



def isevaluable(s):
    try:
        eval(s)
        return True
    except:
        return False

      

But remember that then you will execute your string, which can overshadow your result by putting it in your list.
For example, if your string rm /tmp/cache.txt

that will give a positive result in yours isevaluable

and a negative result in yours [eval(x) ...]

is because it was removed in the try statement.

In this case, compile()

is the best alternative. This is probably in any example.

+1


source


First of all, if your x

only contains a literal of type - strings, numbers, tuples, lists, dicts, booleans and None - you can use ast.literal_eval

, which is much safer than a function eval()

.

ast.literal_eval (node_or_string)

It is safe to evaluate a node expression or Unicode or Latin-1 encoding containing a Python literal or container display. A string or node can only contain the following Python literary structures: strings, numbers, tuples, lists, dicts, booleans, and None.

Also, you will most likely have to define the function yourself isevaluatable()

, like -

def isevaluatable(s):
    import ast
    try:
        ast.literal_eval(s)
        return True
    except ValueError:
        return False

      

Then you can do



import ast [ast.literal_eval (x) if isevaluatable (x) else x for x in some_list]

An easier way to do this is to force the function to return the required value

def myeval(s):
    import ast
    try:
        return ast.literal_eval(s)
    except ValueError:
        return s

      

And then do -

[myeval(x) for x in some_list]

      

0


source







All Articles