eval vs. exec
Michael Hudson
mwh at python.net
Mon May 27 12:53:09 EDT 2002
Simon Budig <Simon.Budig at unix-ag.org> writes:
> Alexander Schmolck <a.schmolck at gmx.net> wrote:
> > Simon Budig <Simon.Budig at unix-ag.org> writes:
> >
> > The distiction is quite simple: use eval for expressions and exec for
> > everything else. That of course only works if you know what qualifies as an
> > expression in python :)
>
> I think I do know what an expression is - what I do not know is
> how to determine the type to use from a string given by an external
> source.
Hmm. Maybe compile as "single" but smash the last PRINT_EXPR into a
RETURN_VALUE? Might work. You'd probably want to turn all but the
last PRINT_EXPR into POP_TOPs too...
Something like this?
import new, dis
POP_TOP = dis.opname.index("POP_TOP")
PRINT_EXPR = dis.opname.index("PRINT_EXPR")
RETURN_VALUE = dis.opname.index("RETURN_VALUE")
def super_eval(expr):
code = compile(expr, "", "single")
codestring = code.co_code
newcode = ""
last_i = 0
i = 0
while i < len(codestring):
op = ord(codestring[i])
if op > dis.HAVE_ARGUMENT:
newcode += codestring[i:i+3]
i += 3
elif op == PRINT_EXPR:
last_i = i
newcode += chr(POP_TOP)
i += 1
else:
newcode += chr(op)
i += 1
if last_i > 0:
newcode = newcode[:last_i] + chr(RETURN_VALUE) + newcode[last_i+1:]
code = new.code(code.co_argcount, code.co_nlocals, code.co_stacksize,
code.co_flags, newcode, code.co_consts, code.co_names,
code.co_varnames, code.co_filename, code.co_name,
code.co_firstlineno, code.co_lnotab)
return eval(code)
>>> super_eval("a = 2")
>>> super_eval("3*4")
12
>>> super_eval("a = 2; b = 3; a*b")
6
buyer-beware-ly y'rs
M.
--
I think my standards have lowered enough that now I think ``good
design'' is when the page doesn't irritate the living fuck out of
me. -- http://www.jwz.org/gruntle/design.html
More information about the Python-list
mailing list