The Python HTMLgen Module
This article is about using HTMLgen, a Python-class library for generating HTML. Python is an object-oriented scripting language that ships with most Linux distributions. It plays a major role in configuration and management for distributions such as Caldera and Red Hat. HTMLgen is an add-on Python module written by Robin Friedrich, and available from http://starship.python.net/lib.html under a BSD-style freeware license.
HTMLgen provides classes to support all the standard HTML 3.2 tags and attributes. It can be used in any situation where you need to dynamically generate HTML. For example, you might want to format the results of a database query into an HTML table, or generate an HTML order form customized for each client.
I'll introduce HTMLgen by using it to format data found on typical Linux systems. I think the examples are sufficiently straightforward that they can be followed by anyone familiar with HTML and scripting, and without prior knowledge of Python. Just remember that in Python, blocks of statements are indicated by indenting the code—there are no begin/end statements and no curly braces. (In Python, WYSIWYG applies.) Other than this, Python code looks much like that found in any mainstream programming language.
Although Perl is the most commonly used web scripting language, I personally prefer Python. It can achieve results similar to Perl, and I think Python's syntax, coupled with the style established by its user community, leads to a cleaner, simpler style of coding. This is an advantage during both development and maintenance. These same strengths provide a gentler learning curve for new players. Python moves a little away from traditional scripting languages and more toward non-scripting, procedural programming languages. This allows Python scripting to scale well. When a small set of scripts starts to grow to the size of a full-blown application system, the language will support the transition.
Any Python program needing HTMLgen must import it as a module. Starting from bash, here's how I set up and import HTMLgen to create a “Hello World” web page:
bash$ export PYTHONPATH=/local/HTMLgen:$PYTHONPATH bash$ python >>> import HTMLgen >>> doc = HTMLgen.SimpleDocument(title="Hello") >>> doc.append(HTMLgen.Heading(1, "Hello World")) >>> print doc
First, I set the PYTHONPATH to include the directory where the HTMLgen.py module can be found. Then, I start the Python interpreter and use its command-line interface to import the HTMLgen module. I create a document object called doc and add a heading to it.
Finally, I print the doc object which dumps the following HTML to standard output:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <HTML> <!-- This file generated using HTMLgen module. --> <HEAD> <META NAME="GENERATOR" CONTENT="HTMLgen 2.0.6"> <TITLE>Hello World</TITLE> </HEAD> <BODY> <H1>Hello World</H1> </BODY> </HTML>
This is a start, although not an exciting one. HTMLgen is a very good tool for generating HTML tables and lists. The table in Figure 1 was created by the Python script in Listing 1. The data in the table comes from the Linux /proc/interrupts file which details the IRQ interrupts for your Linux PC. On my PC, doing a cat of /proc/interrupts yields:
0: 2348528 timer 1: 42481 keyboard 2: 0 cascade 3: 47735 + serial 4: 75428 + serial 5: 48 soundblaster 8: 0 + rtc 11: 1 NE2000 13: 1 math error 14: 175816 + ide0 15: 216 + ide1
The Python script reads the contents of the /proc/interrupts file and copies the data into an HTML table. I'll describe this process step by step. As in the previous example, I first create a simple document. I then add an HTMLgen table to the document:
table = HTMLgen.Table( tabletitle='Interrupts', border=2, width=100, cell_align"right", heading=[ "Description", "IRQ", "Count" ]) doc.append(table)When creating the table object, I set some optional attributes by supplying them as named arguments. The final headings argument sets the list of column headings that HTMLgen will use. All of the above arguments are optional.
Once I've set up my table, I open the /proc/interrupts file and use the readlines method to read in its entire contents. I use a for loop to step through the lines returned and turn them into table rows. Inside the loop, the string and regular expressions functions are used to strip off leading spaces and split up each line into a list of three data values based on space and colon (:) separators:
Elements of the data list are processed to form a table row by reordering them into a new three-element list consisting of name, number and total calls:
[ HTMLgen.Text(data), data, data ]The outer enclosing square brackets construct a list out of the comma-separated arguments. The first list element, data, is the interrupt name. The interrupt name is a non-numeric field, so I've taken the precaution of escaping any characters that might be special to HTML by passing it though the HTMLgen Text filter. The resulting list is made into a row of the table by appending the list to the table's body:
table.body.append( [ HTMLgen.Text(data), data, data ])Finally, once all lines have been processed, the document is written to interrupts.html. The result is shown in Figure 1.
The simple Table class is designed for displaying rows of data such as might be returned from a database query. For more sophisticated tables, the TableLite object offers a lower-level table construction facility that includes the ability to do individual row/column customization, column/row spanning and nested tables.
Special Reports: DevOps
Have projects in development that need help? Have a great development operation in place that can ALWAYS be better? Regardless of where you are in your DevOps process, Linux Journal can help!
With deep focus on Collaborative Development, Continuous Testing and Release & Deployment, we offer here the DEFINITIVE DevOps for Dummies, a mobile Application Development Primer, advice & help from the experts, plus a host of other books, videos, podcasts and more. All free with a quick, one-time registration. Start browsing now...
- Vigilante Malware
- Non-Linux FOSS: Code Your Way To Victory!
- Disney's Linux Light Bulbs (Not a "Luxo Jr." Reboot)
- Vagrant Simplified
- Libreboot on an X60, Part I: the Setup
- Dealing with Boundary Issues
- System Status as SMS Text Messages
- Bluetooth Hacks
- October 2015 Issue of Linux Journal: Raspberry Pi
- New Products