Python Expression Evaluator Version 2

I have extended my Python Expression Evaluator a bit, adding the main feature to support regular expressions . Regular expressions need to be typed in between slashes and need some input text to be applied to, that’s why now a second input field has been added to the user interface.

Regular expressions are very well supported in Python ( like in Perl ), thus not much additional code is needed to support those:

 1: ...
 2:     if expr[0] == "/":
 3:         m = re.match("\/(.*)\/",expr)
 4:         if m:
 5:             expr2 =
 6:             m = re.match(expr2,input)
 7:             if m:
 8:                 for i in range(len(input)):
 9:                     if i in range(m.start(0),m.end(0)):
 10:                         char = "<strong>%s</strong>" % input[i]
 11:                     else: char = "%s" % input[i]
 12:                     for j in range(1,len(m.groups())+1):
 13:                         if i in range(m.start(j),m.end(j)):
 14:                             char = "<span class='highlighted'>%s</span>" % char
 15:                     output += char
 17:     else:
 18: ...

The Python code above first checks whether input contains a regular expression ( starting with a forward slash ). The first regular expression evaluation (re.match(…; re is the name of the Python module for regular expression supported to be imported at the beginning of the program ) is to get the regular expression itself in between the two slashes, the second regular expression evaluation actually evaluates that regular expression. m is the name of the object returned by the evaluation, having some useful attributes:

  • contains the matching part of the input
  • m.start(0) contains the starting position of the matching part of the input
  • m.endt(0) contains the ending position of the matching part of the input
  • m.groups() is a list of groups defined in the regular expression to extract part of the input; defined in form of round brackets within the regular expression
  • with n > 0 is content of group n
  • m.start(n) with n > 0 is the starting position of group n
  • m.end(n) with n > 0 is the ending position of group n

Those useful object attributes help to do what I attempt to do with that code: highlight those characters in my input string being in the overall match or in any of the groups: the first case is indicated by a bold font, being contained in a group by yellow background color. Thus my for loop

 1: for i in range(len(input)):

iterates over the input provided character by character.Then I analyze whether that character is contained in the overall match to put some HTML “strong” tags around it. Then I analyze for each group returned …

 1: for j in range(1,len(m.groups())+1):

… whether the character is contained in a group and give it a yellow background in that case. To do this I use a class called “highlighted” defined in my CSS file for this little application:

 1: .highlighted { background: yellow; }

And here it is: version 2 of my Python Expression Evaluator supporting regular expressions

A Python Expression Evaluator

To start going with my first little Python based web application here I came up with Python Expression Evaluator. What is does ? The name says it all: it evaluates Python expressions, which the user can enter into a form and send to the server where this little 25-liner does its work and returns the result plus all the HTML code to render it nicely on the user’s screen:

It allows the user to type in any type of Python expression, like e.g.

  • 80 / 4, or any other type of basic calculation, thus we can use it as a calculator
  • len(“Hellow World!”) – we can use it to compute the length of a given string
  • “Hello World”.count(“o”) to find out how often a particular character shows up in a given string
  • … and many more ( ideas ? )

Here is the code:

 1: #!/usr/bin/python
 3: import cgitb; cgitb.enable()
 5: import cgi
 6: form = cgi.FieldStorage()
 8: expr = form.getvalue('expr', None)
 12: if expr != None:
 13:     try: output = expr + " => " + str(eval(expr))
 14:     except Exception,e: output = "<font color=\"red\">%s => %s</font>" % (expr,e)
 15: else: output = ""
 17: print '''Content-type: text/html
 19: <html>
 20:   <head>
 21:     <title>Python Expression Evaluator</title>
 22:   </head>
 23:   <body>
 24:     <h1>Python Expression Evaluator</h1>
 25:     <div>%s</div>
 26:     <br>
 27:     <form action=''>
 28:     Expression <input type='text' name='expr' />
 29:     <input type='submit' />
 30:     </form>
 31:   </body>
 32: </html>
 33: ''' % output

Let’s decipher what it does:

  1. Let the script know we are using Python code
  2. Import cgitb module and enable CGI Tracebacks to nicely show error messages on the screen rather than in the web server log file. Not really needed here since my little script basically catches all sorts of exceptions, as we will see in a minute. Thanks to Magnus Lie Hetland and his great book “Beginning Python: From Novice to Professional, Second Edition” for this tip !
  3. Import cgi module, mainly used to retrieve values sent to the server
  4. Implement the cgi FieldStorage to retrieve values sent to the server
  5. Evaluate the expression sent to the server. With the help of exception handling all possible exceptions are handled and translated to a message ( variable output ) sent back to the user
  6. Generate the HTML for the user frontend and insert the output message; either the output from the eval() or the exception message.

Try the expression (“10/0″) to see how Python’s exception handling catches that error. If I would remove my own exception handling from the code and change it from

 1: if expr != None:
 2:     try: output = expr + " => " + str(eval(expr))
 3:     except Exception,e: output = "<font color=\"red\">%s => %s</font>" % (expr,e)
 4: else: output = ""

to just

 1: output = expr + " => " + str(eval(expr))

then the cgitb module would kick in and transform the unhandled exception into a message shown in the browser, like here for example:

Nice, so far.

What enhancements can we think of to enhance this little tool ? Here are my ideas, any more to come ?

  1. Support multi-line Python code
  2. Support regular expressions
  3. Support expression storage & retrieval ( partially works thru your browser; try to hit the Down while entry field has focus )
  4. Support a more dynamic user interface
  5. 5. … ?