mod_python exception catching, other repetitious per-page actions

Karl A. Krueger kkrueger at example.edu
Fri Mar 26 17:47:21 CET 2004


I'm in the middle of refactoring a small mod_python Web application,
which uses the Publisher handler.  This application is currently a
single main Python file (which loads several other files as modules)
with several function entry points for the different pages in the
application.

(The application is a tool to allow staff members here to request
firewall port openings for their servers.  Thus there is a page (and
function) for "view my servers", "add a server", "add a service to a
server", and so forth.  Each of these is a function in the published
file.)

One thing I would like to do is factor all of the top-level database
connecting, top-level exception handling, and error-page generation into
a single place.  Whenever an exception occurs not trapped locally --
including an error connecting to the database -- I want to generate an
HTML error page instead of throwing the stacktrace at the user.

Currently this means that every function is one big try/except block
where the except block calls a TypesetErrorPage() function.  Also
repeated are the function calls to set up the database backend
connection and to set up some per-user globals:

def mainpage(apache_request, some_cgi_arg):
	try:
		_connect_to_database()
		# other repetitious stuff here
		_do_user_specific_stuff(apache_request)
		#
		# specific code here
		#
	except Exception, err:
		return _TypesetErrorPage(err)

def addserverpage(apache_request, some_cgi_arg, another_arg):
	try:
		_connect_to_database()
		# other repetitious stuff here
		_do_user_specific_stuff(apache_request)
		#
		# specific code here
		#
	except Exception, err:
		return _TypesetErrorPage(err)

I'd like to factor this repetition out.  However there does not seem to
be a straightforward way to do it -- the connect_to_database() could be
done at the module level (i.e. outside of any function), but this might
have problems if the Apache instance persists long enough between
requests for the database to time out.

One thing I have considered is to handle _all_ the pages through a
single function, which would look up the specific pages by name:

PAGES = { "mainpage" : mainpagefunc, "addserverpage" : addserverfunc }

def page(apache_request, which_page, *args):
	try:
		connect_to_database()
		# other repetitious stuff here
		do_user_specific_stuff(apache_request)
		return PAGES[which_page](req, *args)  # call the real page
	except Exception, err:
		return TypesetErrorPage(err)

... but this has the problem that it sacrifices the argument name
matching which is a major useful feature of mod_python Publisher.  I'm
not sure if keyword args are exactly the Right Thing either.  It also
would make the URLs even longer than they already are, though I can
kludge that with Apache URL rewriting rules.  (Bleah.)

I feel like I want a Lisp macro, but that's a topic I shouldn't even
invoke.  Forget I said that.  :)

Any thoughts?

-- 
Karl A. Krueger <kkrueger at example.edu>
Woods Hole Oceanographic Institution
Email address is spamtrapped.  s/example/whoi/
"Outlook not so good." -- Magic 8-Ball Software Reviews



More information about the Python-list mailing list