A real answer needs a lot more information (relevant paths, chunks of configuration, is your *.py executable, did you restart after configuration etc) so I'm going to do the best I can, but first...
Unlike PHP which has fastCGI built into the interpreter itself, Python doesn't hide the fastCGI implementation from you. At the very basic level, this test.py sets invalid headers (
\r\n newlines are mandatory) and is missing the required blank line between headers and body. These are both things that the
req.write() functions (as shown in the example) deal with.
Second, you have to write a fastCGI application that runs "forever" (or until it hits the maximum number of requests and the server kills it to start another). Unlike PHP, there isn't a "python-cgi" like "php-cgi" (that I'm aware of, anyway...) that will run forever and handle requests by running little bits of source code from various files.
That app will have a request handler function that is called for every request and is responsible for reading and processing the actual request. In the case of the example given, the
Handler class (which is a subclass of
cgi.Handler) is created and is used to construct a fastCGI server whose
run() method is called to handle the "run forever" part of the question. The class has a
process() member added that accepts the request and does something. This "something" is where you would have your hello world code.
Based on the configuration in the example you linked, when a browser goes to
http://vhost.example.com/python/banana/apple.jpg, litespeed will attempt to connect to an existing
/absolutepathto/demoapp.py process through the socket file at
/tmp/lshttpd/mypythonfcgi.sock (or run the demoapp.py program then connect if necessary). Once it's connected, it uses the fastCGI protocol to tell the running app that it has a request for
REQUEST_URI (I think. It may be /python/banana/apple.jpg or something like that. Use the example given to dump the request and see). It's up to the
process() member function to figure out what to do with the
banana/apple.jpg request. Unlike plain PHP, URLs will not necessarily correspond to individual pieces of source code. (Though you could write a python program that uses REQUEST_URI to execute other python programs.)
Also note that this /absolutepathto/fastcgiapp.py is traditionally outside of your server document root so that people can't accidentally download the app itself.
Now, as to why your script is being printed out instead of throwing a bad header error, giving you a blank page, or just crashing. Leading suspects are one of the three:
- your "
/absolutepathto/test.py" isn't executable (though I'm sure this would cause an error)
- your virtualhost in litespeed isn't configured with your test.py as an "External App" (this could also be configured at the server level for all virtualhosts)
- your URI on that virtualhost isn't configured to route requests to your "External App" configured in step #2.
- you didn't restart litespeed after changing the configuration for #2 and #3? (not really a leading suspect but gotta ask)
If it isn't #1 or #4, update the question with your relevant litespeed configuration, and we'll go from there.