You are hereBlogs / marv's blog / Python Coolness 3: The Talking Web-Service
Python Coolness 3: The Talking Web-Service
Today I am going to show you how to make a cool little web-service to impress all (and none other than) your geeky friends. Now I hear you saying "Web-App? Oh I know how to do that! Start Apache (or Web Sharing) and pop a python CGI into that shared directory. Big deal." But, that would be the old (read: boring) way of doing things, and we here are going to do things the Python way. Now I should mention that the tutorial here is going to be Mac only, but that the idea can be transferred to a platform of your choice. The reason I chose to use Mac-specific technology is so that our web-service actually has a use, namely: Use Mac speech on a non-Mac computer.
So, let's say you are at school or Uni or your buddy's place, and you are happily command-lining your way around a Linux box. Now, you are happy (since your not stuck on Vista), but you'd be even more happy if you could hear your favorite Mac synthetic voice let out a "That's what she said" every other minute, until everyone in the room has gone quietly insane. Well, we are about to make that dream come true.
What we want to do, is have a web page, where you can enter any string, and download a spoken audio version of it. It turns out, we will need a mere 30 lines of code (that's with the HTML) to make this happen. And by the way, we won't need Apache or any of the sorts. So the first thing we want to make sure, is that CherryPy >3.0 is installed. I recommend installing this with either MacPorts or Fink. For instance, for Python 2.5 and MacPorts you could install it like this:
sudo port install py25-cherrypy3
So what does CherryPy do? Well, it is a web application framework designed for rapid development of web applications by wrapping the HTTP protocol. It does that, not much more, but does that right. So let's get right into coding. We begin by importing the modules we'll need.
import os from random import randint import cherrypy from cherrypy.lib import static
We'll need the os module for file handling, and the random module for creating a temporary file. Next, we import the cherrypy module for our website, and also import a sub-module, which we'll need for the downloading of the audio file.
Next up, we'll code our web page in HTML. We'll store this in a string.
siteHTML="""
<html>
<title>Talking Website</title>
<body>
<h1>Welcome to the talking web service!</h1>
Enter something to say here:<br/>
<form action="say" method="post">
Text: <input name="textToSay" type="text">
<input type="submit" value="Say!">
</form>
</body>
</html>
"""So, as you see, we have made a very bare-bones web page with a form where text can be entered. Now let's use the magic of CherryPy to make this web page accessible. We begin by defining a class that wraps the functionality of our page. We return the HTML string in a method called index:
class Talker: @cherrypy.expose def index(self): return siteHTML;
You see, CherryPy maps the requested URL paths to methods of your class. So, when a user surfs to your index page (the default path), our HTML string is returned, and rendered in the browser. The cherrypy.expose tells CherryPy, that this method should be accessible over HTTP. To start our web server, we simply append the following line to the end of our code:
cherrypy.quickstart(Talker())
Try it! Run your python script from the command line, and point your favorite browser to http://localhost:8080. You will be greeted with your website. No Apache required! Of course, our talking service does not work yet: When we hit the say button, we are redirected to a non-existant path on our website (namely, to http://localhost:8080/say along with the values entered in the form). Again, we can use the mapping mechanism of CherryPy, and simply add a say method to our class:
@cherrypy.expose def say(self, textToSay="I am error"): soundfile = "/tmp/speech.%d.aiff" % randint(0,10000) os.system("/usr/bin/say -o %s %s" % (soundfile, textToSay)) return static.serve_file(soundfile, "audio/x-aiff", "attachment", "speech.aiff")
So let's go through this. When comparing our method signature to our HTML form, we see that the textToSay parameter is mapped directly to the parameter of our method. We provide a default value in case someone goes to the say page without specifying any parameters. Next, we create a random file path in a temporary directory. This directory is regularly cleaned by the system. The os.system function runs the say command, which is available on Mac OS X to output speech. Enter man say on the command-line to learn more about this command. We write the speech audio data to an AIFF file. Finally, we use CherryPy to serve the file as an audio download.
Once you save the file, CherryPy will automatically restart the web-service (cool, huh?). Try it out! Type something into the text field, and hit "Say!". A download will start with the audio version of your (presumably obscene) entered string.
Now, of course your Linux buddy, will be rolling his eyes for you actually having to leave the command-line to start a GUI front-end. This is however, not the case. Of course we can visit the say service directly, without going through our web front-end. To do this we use curl. For instance, launch terminal, and try this:
curl -F 'textToSay="Any questions, noob?"' http: //localhost:8080/say > lilspeech.aiff
(Note, the space in the URL must be omitted. It is used here only, so that Drupal's auto-formatting does not kick in). On linux you can then use some tool like play or aplay to play the audio file. On the Mac you can either or use open, or (if on Leopard) you can do a little trick like:
qlmanage -p lilspeech.aiff This will give you a QuickLook preview of the audio file.
Anyway, that sums it up for this edition of Python Coolness. As you can see, you can use such a web-service to accomplish many tasks remotely. I often use CherryPy for making platform-independant, remotely-accesible graphical front-ends to complex underlying systems. Here are a few other ideas:
- Screenshot
- Use the screencapture utility to be able to download screenshots of your Mac remotely. Be careful though, since anyone may be able to observe you, if you do not implement some sort of password protection.
- Image Processing
- Use PIL (Python Image Library) to perform image processing or rendering, and provide that as a Web Service.
- Remote Process
- Move expensive processes to a remote computer. For instance, you could submit files for compiling to your web-service, which would pipe these files to gcc.
- Monitoring
- Use CherryPy to display an up-to-date version of the status of your server. Things like memory and CPU usage, or CPU temperature could be displayed on a web-page.
I hope this inspires you to try more things with CherryPy. You will see that it can really make things easier, especially when you are away from home.
- marv's blog
- Login to post comments