eval to dict problems NEWB going crazy !

Fredrik Lundh fredrik at pythonware.com
Fri Jul 7 13:57:02 EDT 2006


Steven D'Aprano wrote:

> Personally, I would never use eval on any string I didn't write myself. If
> I was thinking about evaluating a user-string, I would always write a
> function to parse the string and accept only the specific sort of data I
> expected. In your case, a quick-and-dirty untested function might be:

for a more robust approach, you can use Python's tokenizer module, 
together with the iterator-based approach described here:

     http://online.effbot.org/2005_11_01_archive.htm#simple-parser-1

here's a (tested!) variant that handles lists and dictionaries as well:

     import cStringIO, tokenize

     def sequence(next, token, end):
	out = []
	token = next()
	while token[1] != end:
	    out.append(atom(next, token))
	    token = next()
	    if token[1] == "," or token[1] == ":":
		token = next()
	return out

     def atom(next, token):
	if token[1] == "(":
	    return tuple(sequence(next, token, ")"))
	elif token[1] == "[":
	    return sequence(next, token, "]")
	elif token[1] == "{":
	    seq = sequence(next, token, "}")
	    res = {}
	    for i in range(0, len(seq), 2):
		res[seq[i]] = seq[i+1]
	    return res
	elif token[0] in (tokenize.STRING, tokenize.NUMBER):
	    return eval(token[1]) # safe use of eval!
	raise SyntaxError("malformed expression (%s)" % token[1])

     def simple_eval(source):
	src = cStringIO.StringIO(source).readline
	src = tokenize.generate_tokens(src)
	src = (token for token in src if token[0] is not tokenize.NL)
	res = atom(src.next, src.next())
	if src.next()[0] is not tokenize.ENDMARKER:
	    raise SyntaxError("bogus data after expression")
	return res

(now waiting for paul to post the obligatory pyparsing example).

</F>




More information about the Python-list mailing list