from ast import parse, NodeTransformer, dump, Call, Name, Load, \ fix_missing_locations, Str class Basic(object): def __init__(self, *args): self._args = args def __div__(a, b): return Div(a, b) def __mul__(a, b): return Mul(a, b) class Mul(Basic): pass class Div(Basic): pass class Real(Basic): pass class Integer(Basic): pass class Transform(NodeTransformer): def __init__(self, local_dict, global_dict): NodeTransformer.__init__(self) self.local_dict = local_dict self.global_dict = global_dict def visit_Num(self, node): if isinstance(node.n, int): return fix_missing_locations(Call(Name('Integer', Load()), [node], [], None, None)) elif isinstance(node.n, float): return fix_missing_locations(Call(Name('Real', Load()), [node], [], None, None)) return node def visit_Name(self, node): if node.id in self.local_dict: return node elif node.id in self.global_dict: name_obj = self.global_dict[node.id] if isinstance(name_obj, (Basic, type)) or callable(name_obj): return node elif node.id in ['True', 'False']: return node return fix_missing_locations(Call(Name('Symbol', Load()), [Str(node.id)], [], None, None)) def visit_Lambda(self, node): if len(node.args.args) == 0: args = [Str("x")] else: args = node.args.args args = [self.visit(arg) for arg in args] body = self.visit(node.body) n = Call(Name('Lambda', Load()), args + [body], [], None, None) return fix_missing_locations(n) def parse_expr(s, local_dict): """ Converts the string "s" to a SymPy expression, in local_dict. It converts all numbers to Integers before feeding it to Python and automatically creates Symbols. """ global_dict = globals() a = parse(s.strip(), mode="eval") a = Transform(local_dict, global_dict).visit(a) e = compile(a, "", "eval") return eval(e, local_dict, global_dict) print parse_expr("1", {}) print parse_expr("1/2", {}) print parse_expr("1*2", {})