3

I want to evaluate an expression in Python 3.7 that is read as string from a config file. The application is a Datalogger and the user shall be able to define his own conversion of the raw ADC value in the config file. Using eval() and compile() is handy, but is considered to be unsafe. I tried to use ast.literal_eval() but it does not work with Python 3.7, because it doesn't allows using operators like +-*/. Finally I came up with something like this:

def convert(code, value):
    try: 
        return eval(code, {'__builtins__': {}}, {'value': value})
    except RecursionError as e:
        print(str(e))
    except NameError as e:
        print(str(e))

def compile_expression(expr):

    if '__' in expr:  # check for double underscore
        print('expression contains illegal characters')
        return None
    try:
        code = compile(expr, '<String>', 'eval')  # compile it for use with eval
    except SyntaxError as e:
        print('Invalid Syntax in expression. Using default value.')
        code = compile('value', '<String>', 'eval')       
    return code

expr = '(value-1)/0.005'         # string is read from a config file
code = compile_expression(expr)  # compile string 

if code is not None:
    t = convert(code, 1.1) # convert ADC value to temperature
    print(t)

At least I tried to make it as safe as I can. Does anyone have a suggestion how to do better or has a suitable alternative to eval() and compile()?

jnzerror
  • 39
  • 3
  • I read the similar qusetion above before. It explains a lot (very usefull) about `eval()` and `ast.literal_eval()` but finally it does not answer how to evaluate safely an expression containing operators in Python 3.7. The only solution I found is the code above, which I hope is not totally unsafe. – jnzerror Jun 07 '20 at 19:22

0 Answers0