safe eval of moderately simple math expressions

Joel Hedlund joel.hedlund at gmail.com
Thu Apr 9 11:56:49 EDT 2009


Hi all!

I'm writing a program that presents a lot of numbers to the user, and I 
want to let the user apply moderately simple arithmentics to these 
numbers. One possibility that comes to mind is to use the eval function, 
but since that sends up all kinds of warning flags in my head, I thought 
I'd put my idea out here first so you guys can tell me if I'm insane. :-)

This is the gist of it:
----------------------------------------------------------
import math

globals = dict((s, getattr(math, s)) for s in dir(math) if '_' not in s)
globals.update(__builtins__=None, divmod=divmod, round=round)

def calc(expr, x):
     if '_' in expr:
         raise ValueError("expr must not contain '_' characters")
     try:
         return eval(expr, globals, dict(x=x))
     except:
         raise ValueError("bad expr or x")

print calc('cos(x*pi)', 1.33)
----------------------------------------------------------

This lets the user do stuff like "exp(-0.01*x)" or "round(100*x)" but 
prevents malevolent stuff like "__import__('os').system('del *.*')" or
"(t for t in (42).__class__.__base__.__subclasses__() if t.__name__ == 
'file').next()" from messing things up.

I assume there's lots of nasty and absolutely lethal stuff that I've 
missed, and I kindly request you show me the error of my ways.

Thank you for your time!
/Joel Hedlund



More information about the Python-list mailing list