1

my situation is as follows:

  1. I have a large table like object which is accessed with a string key and integer index; i.e. lookup is like this: value = table.get("Key", index) .
  2. I would like to give the user the opportunity to enter an arbitrary algebraic expression involving the string keys. The code code should then iterate over the second index and evaluate the expression repeatedly.

So for user input like this: "KeyA + 2*math.abs(KeyC)" I would like to run python code resembling:

for index in index_list:
    answer = table.get("KeyA", index) + 2*math.abs(table.get("Keyc",index))

I guess can parse the expression using one of the Python Parser libraries I found on the internet, but it is not by any means clear to me how actually "run" the parsed code. Any suggestions?

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
user422005
  • 1,989
  • 16
  • 34
  • I think that there is something wrong with that for, you keep assigning results to the same variable. – smeso Dec 09 '13 at 21:07
  • 1
    If you get the input parsed into valid python code you can use eval() – M4rtini Dec 09 '13 at 21:11
  • Well I have thought about eval() - but I would like to do the looping over the second index on the 'outside'. – user422005 Dec 09 '13 at 21:27
  • 1
    @M4rtini It's a bad idea to use eval, it can run arbitrary code, and is a vulnerability if user input allowed as source – alko Dec 09 '13 at 21:34
  • @alko I was assuming he was gonna parse the input with the mentioned "Python Parser libraries". My assumption that this would give safe code might have been wrong though. – M4rtini Dec 09 '13 at 21:37

1 Answers1

1

If your end users can enter variables in figure brackets, {..}, you can use str.format to format your string

>>> expression = '{a}*{b}'
>>> values = {'a': 10, 'b': 20, 'c': 30} 
>>> expression.format(**values)
'10*20'

Here values dictionary might be filled with table.get for all keys found in expression, for example with a regular expression:

>>> import re
>>> regexp = re.compile('{(.*?)}')
>>> keys = regexp.findall(expression)
>>> keys
['a', 'b']
>>> table_get = lambda *x: np.random.randint(5)
>>> values = {k: table_get(k) for k in keys}
>>> expression.format(**values)
'1*4'

Then you can refer to Safe way to parse user-supplied mathematical formula in Python for safe expression parsing and evaluation.

Community
  • 1
  • 1
alko
  • 46,136
  • 12
  • 94
  • 102