I am coding a kind of command line user interface where an arbitrary boolean expression can be given as input. This expression must be repeatedly evaluated on a dictionary that is changing after some update.
Here is the simplified code :
import traceback
def update_my_dict():
return {'a': 1}
my_dict = {'a': 0}
bool_exp = input()
# -- verify code can be executed in the current context
try:
result = eval(bool_exp, my_dict)
except Exception:
print(f'Expression cannot be evaluated, evaluation raise the following error:')
print(traceback.format_exc())
quit()
# -- verify code return a boolean
if not isinstance(result, bool):
print(f'Expression return {type(result)}, expect bool')
quit()
# -- go
while not eval(bool_exp, my_dict):
my_dict = update_my_dict()
Before running the last while loop I want to verify that the expression can be executed in the current context and ensuring that its return a boolean.
My problem is if the expression is, for example bool_exp = a == 1 and b == 2
the first test evaluation of the expression while return false but do not raise exception because off lazy evaluation. But when my_dict
is updated then an error will be raised.
So is that possible to, some how, disable the lazy/short-circuit evaluation for the first test evaluation ? I searched some solution using ast, but it seems complicated since bool_exp
can be arbitrary long and complex, like containing entangled boolean expressions and so on.
PS: I know eval()
is unsafe in a general context but my code will not be usable externaly
PS2: I know its possible to catch the exception in the while loop but it looks a bit sub-optimized knowing my_dict
keys will never change when updated, only their values. Also this question is more like if its possible to control the evaluation behavior
EDIT
"but you could use &
and |
instead of and
and or
!"
No. I cannot tell what will be entered as input. So the user can input whatever s.he want.
A Correct input expression:
- Should return a boolean.
- Should only involve dictionary keys in the tests.
"Correct" meaning it will be repeatedly evaluated in the ending while loop without raised any exception.
We assume that the keys in the dictionary will stay constant. i.e only the values of the dict will change during the update phase. In other words, the first try/except
aim to verify that the expression is only doing some test on variables that are in my_dict
.
I cannot explain further the global use of this or I'll need a very long post with lost of what seems irrelevant information to resolve the issue.