replacement of rexec?

Huaiyu Zhu huaiyu at gauss.almaden.ibm.com
Tue Nov 4 22:01:08 EST 2003


In article <698f09f8.0310301113.356fd637 at posting.google.com>, Jeremy
Fincher wrote: 
> Skip Montanaro <skip at pobox.com> wrote in message news:<mailman.242.1067527420.702.python-list at python.org>...
>> I'm not aware of anything.  Assuming your inspection process shows the file
>> is okay, why not just call execfile()?
> 
> 
> Probably because that won't get him a useful value :)  He'd have to
> use eval (but you probably knew that and just typo'ed execfile; I'm
> mostly just saying it to try and prevent confusion on his part).

That's the point - the file contains multiple strings to be converted to
python objects.  I've written the following code over the weekend.  It is
more complicated than I'd like.  Hopefully someone can replace part or all
of it by some builtin functionality.

#-------------------------------------------------------
import compiler
def safe_eval(s):
    """
    Evaluate strings that only contains the following structures:
    const,  tuple,  list,   dict
    """
    stmts = compiler.parse(s).node.nodes
    #print stmts
    assert len(stmts) == 1
    node = compiler.parse(s).node.nodes[0]
    assert node.__class__ == compiler.ast.Discard
    nodes = node.getChildNodes()
    assert len(nodes) == 1
    return safe_assemble(nodes[0])

seq_types = {
    compiler.ast.Tuple: tuple,
    compiler.ast.List: list,
    }
map_types = {
    compiler.ast.Dict: dict,
    }

def safe_assemble(node):
    """ Recursively assemble parsed ast node """
    cls = node.__class__
    if cls == compiler.ast.Const:
        return node.value
    elif cls in seq_types:
        nodes = node.nodes
        args = map(safe_assemble, nodes)
        return seq_types[cls](args)
    elif cls in map_types:
        keys, values = zip(*node.items)
        keys = map(safe_assemble, keys)
        values = map(safe_assemble, values)
        return map_types[cls](zip(keys, values))
    else:
        raise "Type not allowed", cls


if __name__ == '__main__':
    tests = [
        "3j",
        "1, 2.5",
        "['abc', 0xF7]",
        "1, ['abc', [2,3]], {(4,5):[6.5, 8]}",
        ]
    for s in tests:
        print safe_eval(s)
#-------------------------------------------------------


Huaiyu




More information about the Python-list mailing list