Steffen Ebermann wrote:
Hi,

this might be a little off topic (could be any other language) but I'm trying to set up Python to use FastCGI instead of plain CGI.

The basic setup is no problem but every tutorial (including Python's 'HOWTO Use Python in the web') ends with some basic dispatch file and that's it. I guess I should know how to go about from there, but,
well I don't.

I guess I could put an execfile('index.py') into the dispatcher and
then rewrite my code for FastCGI (i.e. replace every print with
req.write() for jonpy), but that doesn't seem right to me.

Is there a better solution or do I misunderstand something entirely?
I would be glad if someone could point me in the right direction.

Thanks in advance.

   You don't print in an FCGI program.  At the end of the function,
you return a reply string.

   Here's the main program of a live FCGI application.  This is
from something that answers XMLHttpRequest request, rather than
serving HTML pages.  So it outputs XML.

Things to note:

1. FCGI programs can run for a long time, like days. So you
have to handle the possible loss of a database connection, as
is done here.

2. Catch and handle all exceptions.  FCGI won't give you much
information in the error log.

3. You have to specify everything that goes in the HTTP headers
by calling start_response().

4. Notice the last line:
        WSGIServer(QuickSitetruthQuery).run()

That's the call which tells WSGIServer what function to call
for each request.

5. If you put an FCGI file in a directory from which Apache
will run CGI files, your FCGI program will be run as a CGI
program.  Everything will appear to work, because the FCGI
library understands this is a debug mode.  But you're loading
the program on each use, so the overhead is huge, as with CGI.
CGI is built into Apache at too low a level, and it will run
something as CGI even when you've told it a directory is
supposed to be used for FCGI.  So create an "fcgi" directory
someplace other than "cgi" and tell Apache to use that for
FCGI.

FCGI is a good system; it's just that the documentation isn't
very good.    This code has been running a live
web site for two years now.
        

                                        John Nagle

#!/usr/local/bin/python
### ... application-specific stuff deleted
from fcgi import WSGIServer
import MySQLdb
import cgi                                                                      
        import urllib
import InfoDisplay                                                              
        import miscutils
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
            except MySQLdb.OperationalError, message:   # loss of conn.
                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
            needretry = outstr.find('status="202"') >= 0   # if retry soon
            if needretry :      # if the client will need to retry this request
                headers.append(('Expires','-1')) # expire immediately
            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()
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to