Ideas to optimize this getitem/eval call?

mario mario.ruggier at
Sat Jan 3 02:29:29 CET 2009


below is the essence of a an expression evaluator, by means of a
getitem lookup. The expression codes are compiled and cached -- the
lookup is actually recursive, and the first time around it will always

import sys
class GetItemEval(object):

    def __init__(self):
        self.globals = globals() # some dict (always the same)
        self.locals = {} # some other dict (may be different between
evaluations) = {} # compiled code expressions cache

    def __getitem__(self, expr):
            return eval([expr], self.globals, self.locals)
            # KeyError, NameError, AttributeError, SyntaxError,
            # TypeError, IOError
            # Special case if a KeyError is coming from the
            # lookup (traceback should consist of a single frame
            if sys.exc_info()[2].tb_next is None:
                if sys.exc_info()[0] is KeyError:
          [expr] = compile(expr, '<string>',
                    return self[expr]
            # otherwise handle eval error in some way...

This class could be used in a way as follows:

# define some expressions
def f(s): return "["+s+"]"
exprs = ["1+2+3", "2*3*5", "f(__name__)"]
# instantiate one
gie = GetItemEval()
# use it to lookup/eval each expression
for x in exprs:
    print x, "=", gie[x]

And, fwiw, some sample timeit code:

import timeit
print timeit.Timer("for x in exprs: gie[x]",
        "from __main__ import gie, exprs").timeit(500000)

I had done various poking to discover if it could be made to go
faster, and in the end I settled on the version above.


Incidentally this constitutes the lion's share of the evaluation
runtime of evoque templating...

More information about the Python-list mailing list