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)]
source to share
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.
source to share
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]
source to share