Home > OS >  How to eval list indices in a safe way?
How to eval list indices in a safe way?

Time:11-26

I try to evaluate some Python expressions like [1, 2, 3][1]. I can't use eval('[1, 2, 3][1]') because every time I do that, a kitten might die. A safer way is to use ast.literal_eval('[1, 2, 3][1]'), however, it raises a ValueError:

ValueError: malformed node or string ...

What can be done in order to make it work? Thanks in advance.

CodePudding user response:

There might be some better way, but if the format is just as you describe (a list literal followed by an index literal in square brackets), then you can separate it into parts, evaluate them individually, and then combine them in your logic.

import re
from ast import literal_eval
string = '[1, 2, 3][1]'
m = re.match(r'^(\[. \])\[(. )\]$', string)
mylist = literal_eval(m.group(1))
index = literal_eval(m.group(2))
value = mylist[index]
# gives value 2

CodePudding user response:

If it's as simple as selecting integer from list, you could parse it yourself.

s = "[1, 12, 30][-1]"

def foo(s):
    arr = []
    curr = ""
    for c in s:
        if c.isdigit() or c in ["-"]:
            curr  = c
        elif c == "," or c == "]":
            arr.append(int(curr))
            curr = ""

    lst, ind = arr[:-1], arr[-1]
    return lst[ind]
    
foo(s)
# 30

Or maybe

arr, ind = (
    s.replace("][", ";").replace("[", "").replace("]", "").replace(" ", "").split(";")
)
int(arr.split(",")[int(ind)])

CodePudding user response:

You can safely produce an AST from the input, using the compile built-in. But you cannot safely evaluate the AST. So you'll have to walk the AST yourself, collecting the literal integers and making a list out of them. If the expression is as simple as you say, that won't be difficult.

  • Related