Python Servlet Engine

"So simple and elegant, yet extremely powerful."
- PSE User

PSE Tutorial

This is a tutorial that will teach you to use PSE by creating a sample application. It will start with the most basic implementation and build up to more complex uses, such as creating a custom tag.

Hello, world!

Why not? Everybody else starts here. This is very simple to do in PSE.
<html>

  <head>
    <title>Sample PSE Application</title>
  </head>

  <body>
    <? print "Hello, world!" ?>
  </body>

</html>
Listing 1: hello1.pt

In this listing you will notice the pre-processor directive being used to indicate embedded Python code. In this case, the print statement is being used to print "Hello, world!" in the HTML. Notice that the indentation of the Python code doesn't matter here, since the parser will take care of any white space to make sure proper indentation is maintained in the resulting servlet. Incidentally, this template will compile to the following result:

sys.stdout.write('''<html>

  <head>
    <title>Sample PSE Application<title>
  <head>

  <body>
    ''')
print "Hello, world!"
sys.stdout.write('''<body>

<html>
''')
Listing 2: hello1.pty

If the apache process has permission to write in the directory, PSE will generate an intermediate file with the servlet source, in this case hello.pty. This can be an aid in debugging when something goes wrong, because you can see what source code was generated to help you track down a bug. There is also a final compiled version of the servlet, in this case hello.ptc, but this is a byte compiled file that cannot be viewed textually.

The result of this servlet is, of course, a simple page with only the text "Hello, world!" printed in the browser. Notice that we used the print statement here. Normally you should never use print in a PSE servlet, especially when using custom tags. The reason for this is explained in the PSE manual, but it will become more apparent later. The proper way to produce output in the HTML is to use the <?= ... ?> construct as such:

<html>

  <head>
    <title>Sample PSE Application</title>
  </head>

  <body>
    <?="Hello, world!" ?>
  </body>

</html>
Listing 3: hello2.pt

This construct will actually convert whatever the expression evaluates as into a string for use by PSE. In this case, the result is directly send to stdout as in the following listing:

sys.stdout.write('''<html>

  <head>
    <title>Sample PSE Application<title>
  <head>

  <body>
    ''')
sys.stdout.write(str("Hello, world!"))
sys.stdout.write('''<body>

<html>
''')
Listing 4: hello2.pty

While it seems that there is practically no difference from this servlet and the first one using print, PSE handles this differently when it comes to using custom tags. We'll cover custom tags later in this tutorial, but it is sufficient to say that you should almost always use <?= ... ?> instead of print.

Making It Personal

You can access form variables in PSE using the built-in dictionary pse.form. This dictionary will contain GET as well as POST variables. The values are often strings, however duplicate form element names result in a list, while file uploads result in a file-like object.

<html>

  <head>
    <title>Sample PSE Application</title>
  </head>

  <body>
    <?="Hello, %s!" % pse.form['name'] ?>
  </body>

</html>
Listing 5: hello3.pt

Now if you access the page in your browser, you'll get a traceback from a KeyError exception. To access this page properly, add a query string such as hello3.pt?name=Nick to get the output, "Hello, Nick!" Notice how the PSE template could have been much more easily written as:

    Hello, <?=pse.form['name'] ?>

Further, you could eliminate the possiblity of a KeyError by testing for the existence of the correct form variable.

    <? if pse.form.has_key('name'): ?>
      Hello, <?=pse.form['name'] ?>
    <? :else: ?>
      Hello, world!
    <? :if ?>

Notice how the colon (:) helps PSE control indentation across several directives. By viewing the parsed code, you can see how the proper indentation is maintained:

sys.stdout.write('''<html>

  <head>
    <title>Sample PSE Application<title>
  <head>

  <body>
    ''')
if pse.form.has_key('name'):
 sys.stdout.write('''
      Hello, ''')
 sys.stdout.write(str(pse.form['name']))
else:
 sys.stdout.write('''
      Hello, world!
    ''')
sys.stdout.write('''<body>

<html>
''')

Listing 6: hello3.pty

How you use PSE will be up to you. You could also create a form that has a text input element called "name" and submit it to this servlet. It can be a GET or POST method, but the result will be the same.

Separating the Code

Some people like to embed Python as much as possible into the template, while others prefer an approach that separates the code as much as possible from the template. PSE allows you to do both. In our last example, we can conduct the error checking in a separate module that gets executed with the template.

<html>

  <head>
    <title>Sample PSE Application</title>
  </head>

  <body>
    Hello, <?=name ?>!
  </body>

</html>
Listing 7: hello4.pt
if pse.form.has_key('name'):
    name = pse.form['name']
else:
    name = 'world'
Listing 8: hello4.py

Notice that the Python module has the same base name as the template file. PSE recognizes this as a Python module that should automatically be executed before the template file, making a complete servlet. Normally PSE will keep these files separate, but with the PSE compilation utility you can compile both files to a single hello4.ptc file.

More to come...
Copyright ©2003-2005 by Nicholas Borko. All Rights Reserved.