Knowledgebase: How-To
Using Python with FastGCI
Posted by on 02 July 2012 11:03 AM

Plain Old Python with FastCGI


The first part of these instructions are similar to Django on FastCGI. First, obtain shell access and then

cd ~/www
mkdir project
cd project
wget h p://svn.saddi.com/py-lib/trunk/fcgi.py
chmod 755 fcgi.py


FastCGI works based on a .fcgi file and it detects reloads based on timestamps. For this reason and that you probably don't want your Python project to be entirely wri en for FastCGI, you probably want to use .htaccess to route everything through a dispatch.fcgi file as Django does. First, the < >project/.htaccess:

RewriteEngine On
RewriteBase /project

RewriteCond %{REQUEST_URI} !^/project/dispatch.fcgi [NC]
RewriteCond %{REQUEST_URI} !^/project/static [NC]
RewriteCond %{REQUEST_URI} !^/project/more_static [NC]
RewriteCond %{REQUEST_URI} !\.(css|png|jpg|gif)$ [NC]
RewriteRule ^(.*)$ dispatch.fcgi/$1 [QSA,NC]


You can add more lines to ignore folders as we did in the example < >static and < >more_static folder or include more file extensions to ignore. That way those files aren't routed through our dispatcher and will be efficiently served by Apache instead. Note that we are appending URLs to < >dispatch.fcgi, which we can parse later with the < >urlparse library and < >cgi.FieldStorage.

Now, create < >project/dispatch.fcgi with Unix line endings. You will receive puzzling FastCGI errors if you use any other line endings, especially if you are on Windows like me and don't like spending hours on end diagnosing puzzling FastCGI errors.

#!/usr/bin/env python

# This must be in Unix line endings
import sys
from fcgi import WSGIServer
import application
import cgi

class Request(object): pass
def app(e, start_response):
  req = Request()
  # POST data
  req.form = cgi.FieldStorage(fp = e['wsgi.input'], environ = e)
  # GET data
  req.params = cgi.parse_qs(e['QUERY_STRING'])
  start_response('200 OK', [('Content-type', 'text/html')])
  return [application.start(req)]

WSGIServer(app).run()


The script, as above, can employ the environ variables and can call any one of your functions in your application stored in another file such as < >start in < >application.py. From that, you can then actually dispatch to the right module to handle the request based on where < >PATH_INFO is or start your application logic.

Before accessing it and possibly forcing FastCGI to generate a broken cache (see below), type < >python dispatch.fcgi in your shell. You should see some output although the environ variables aren't set properly from the shell. If you see Python errors, though, this is a quick way to partially debug your application without having to go through FastCGI just yet.

Now navigate to < >example.com/project/ or whereever and you should see output. Remember: < >example.com/project/jobs maps to < >example.com/project/dispatch.fcgi/jobs due to < >.htaccess.

Tips

  • If you want to update your application, simply run < >touch dispatch.fcgi in your shell.
  • If your < >dispatch.fcgi is somehow broken, FastCGI may add an error stating that it couldn't get the file to run after three requests and has backed off the reload interval to some ungodly time. (You can see this in the error log from your control panel.) Unfortunately, FastCGI is then unable to detect changes to your file so you need to wait a while before you start fixing the problem. (I can't seem to find a workaround besides renaming < >dispatch.fcgi, but that gets tedious.)
  • By the way, that < >fcgi.py will print to output very useful exceptions and tracebacks if your module throws an uncaught exception using the < >cgitb module. This is, however, undesirable for production web sites since it does expose lines of your code to your users. To remedy this, you can monkeypatch the function or just manually edit the < >Server.error method in < >fcgi.py. (Grep for "cgitb.")
  • To redirect, < >start_response('302 Found', [('Location', url)]).
(4 vote(s))
This article was helpful
This article was not helpful

Comments (0)
Post a new comment
 
 
Full Name:
Email:
Comments:
Help Desk Software by Kayako fusion
ERROR: This domain name (kb.asmallorange.com), does not match the domain name in the license key file help.asmallorange.com.

For assistance with your license, please contact the Kayako support team: https://support.kayako.com