Python on the Web

John Nagle nagle at animats.com
Fri Aug 28 12:18:11 EDT 2009


Graham Dumpleton wrote:
> A few additional comments on top of what others have said.
> 
> On Aug 26, 11:09 am, Phil <phil... at gmail.com> wrote:
>> As I've read elsewhere, "These days, FastCGI is never used directly.

     Actually, FCGI works quite well.  Sitetruth's AdRater
(http://www.sitetruth.com/downloads/adrater.html) uses
FCGI and Python on the server.

     FCGI is basically CGI with process reusability. Each
app gets its own process in its own address space with its
own global interpreter lock.  mod_fcgi in Apache keeps a
supply of such processes around, launching additional ones if there's
heavy request traffic and shutting down existing ones when there
isn't.  Each process handles one transaction after another,
so, unlike CGI, you're not spending all your time loading Python
and its modules.

     Here's the main loop of a real FCGI application.  This uses a small
WSGI library on the Python side.  No "framework" is involved.


#!/usr/local/bin/python
...
from fcgi import WSGIServer
import MySQLdb
db = None	# database connection, held open for life of FCGI
#
#	The application
#
def QuickSitetruthQuery(environ, start_response):
     global db	# static global - active database handle
     try:
         if db :	# if previously attached
             try :
                 db.ping() # test whether connection is still up
             # handle loss of database connection
             except MySQLdb.OperationalError, message:	
                 db = None # we lost database connection
		if db is None :	# if no valid database handle
                     db = miscutils.dbattach(kdbfile)	# connect to database
         status = '200 OK'		# normal status
         headers = [('Content-type','text/xml'), ('charset','utf-8')]
         reqlist = cgi.parse_qsl(environ['QUERY_STRING'])	# Parse params
         priority = 1		# priority of request
         sourceip = environ['REMOTE_ADDR']	# get IP address of client
         urls = []			# list of URLs to check
         for item in reqlist :		# for all items
             (key, value) = item		# extract item
             if key.lower() == 'url' :	# want all "url" items
                 urls.append(value)
             elif key.lower() == 'priority' :	# if priority
                 priority = int(value)	# get priority value
         #	Make request; no waiting, no details
         outstr = InfoDisplay.getratingXMLquick(db, kdbfile, urls,
		priority, sourceip) # get the rating XML, never wait
         start_response(status, headers)		# compose result
         s = kprefixxml + outstr + ksuffixxml	# construct output XML
         return [s.encode('utf8')]		# encode as UTF8
     except Exception, message:		# if trouble, report to user
         #	Error handling
         status = "500 Internal Error on Server"
         response_headers = [("Content-type","text/html")]
         start_response(status, response_headers)
         s = "<h1>Internal error - request not processed.</h1>\n\n"
             + traceback.format_exc()
         s = s.replace("\n","<br>")	# convert to HTML
         return [s]
#
#	Main FCGI program
#
WSGIServer(QuickSitetruthQuery).run()

					



More information about the Python-list mailing list