Displaying Random Images with Simple Python CGI

It is fun and sometimes useful to have random images display on your website. Although there are a lot of examples in PHP [1] [2] and Perl [3] [4] for displaying random images, there are not very many for Python. With only a little code and some help from Python's builtin libraries writing a random image script can be done very easily.

Step Zero: Setting Up

Before we start programming let's set a few things up. First, I am using a set of 5 different images for this tutorial:

If you want to follow along, download them to a directory; or you can grab some images of your own that you would like to use. I'm including multiple file types (PNG, GIF, and JPEG) so our script will work with any kind of image file.

Second, we are going to use Python's built in CGI server for testing. To run the CGI server from the command line, enter:

python -c "import CGIHTTPServer;CGIHTTPServer.test()"

Or you can put that line into a file on your path or in your working folder and run the command (mine is called servecgi) from the directory any time you need to do some testing. To stop the server try Ctrl+C or Ctrl+Break. When testing scripts, they must be in a cgi-bin folder, otherwise they will be treated as readable instead of executable.

Step One: Displaying a static image

If you want to use CGI to display random or dynamic images it makes sense to try something simpler, like displaying a static image.

When you request an image from a web server the server sends a response containing the appropriate headers along with the contents of the file itself [5]. To display a static image we will try to duplicate this behavior.

We will try to output the 1.png file for this example. When Python is run as a CGI script the output of the program is sent to the browser. The appropriate header is sent by printing "Content-type: image/png\n". Once the browser recieves the content-type header you can send the contents of the file. Because we are just reading in the file, we should supply the second parameter to the file function, which is the mode. If you are on Windows you need to use "rb" which opens the file in read-binary mode, if you are on Linux then just use "r".

if __name__ == "__main__":
    print "Content-type: image/png\n"
    print file(r"c:\python\random_img\1.png", "rb").read()
Save this code as step1.py in the cgi-bin folder and run the CGI server. Once you get the message "Serving HTTP on port 8000 ..." open up your browser and go to http://loopback:8000/cgi-bin/step1.py, you should see the image.

Step Two: Finding the file types

Before we get to the random images we must first create a method to determine what kind of file we are sending to the viewer. If the correct content-type is not sent the browser will not know what it is looking at. The easiest way to to do this is to look at the file extension, and use that to lookup the content-type in a dictionary.

ext2conttype = {"jpg": "image/jpeg",
                "jpeg": "image/jpeg",
                "png": "image/png",
                "gif": "image/gif"}

def content_type(filename):
    return ext2conttype[filename[filename.rfind(".")+1:].lower()]

if __name__ == "__main__":
    print "Content-type: %s\n" % (content_type(r"c:\python\random_img\3.jpg"))
    print file(r"c:\python\random_img\3.jpg", "rb").read()
Save this as step2.py and load http://loopback:8000/cgi-bin/step2.py, you should see the 3.jpg.

So instead of typing the content type explicitly, we can now find the appropriate content type based on the name of the file.

Step Three: Random Files

Now we are ready to pick random files. To list the contents of a directory you can use the listdir function from the os module. Randomly picking one object from a list is done by using the choice function from the random module.

from os import listdir
from random import choice

ext2conttype = {"jpg": "image/jpeg",
                "jpeg": "image/jpeg",
                "png": "image/png",
                "gif": "image/gif"}

def content_type(filename):
    return ext2conttype[filename[filename.rfind(".")+1:].lower()]

def isimage(filename):
    """true if the filename's extension is in the content-type lookup"""
    filename = filename.lower()
    return filename[filename.rfind(".")+1:] in ext2conttype

def random_file(dir):
    """returns the filename of a randomly chosen image in dir"""
    images = [f for f in listdir(dir) if isimage(f)]
    return choice(images)

if __name__ == "__main__":
    dir = "c:\\python\\random_img\\"
    r = random_file(dir)
    print "Content-type: %s\n" % (content_type(r))
    print file(dir+r, "rb").read()
Save the file as step3.py and load up http://loopback:8000/cgi-bin/step3.py, it should display a random image in your browser every time you refresh the page.

Next steps

From here you could expand the script to use multiple directories, or randomly serve other kinds of files. We can also use the ideas from here to serve dynamic images.

To see how to serve dynamic images follow along to Part 2: Serving Dynamic Images with Python CGI.

[1]: http://www.alistapart.com/d/randomizer/rotate.txt
[2]: http://photomatt.net/scripts/randomimage
[3]: http://www.tizag.com/tools/randpic.php
[4]: http://rossbeyer.net/software/random_gallery/
[5]: http://en.wikipedia.org/wiki/Web_server