How to setup Python with Lighttpd and FastCGI (like PHP)

Running Lighttpd on Linux, I would like to be able to execute Python scripts just the way I execute PHP scripts.

The goal is to be able to execute arbitrary script files stored in the WWW directory, e.g. http://www.example.com/*.py.


  • I would not like to spawn a new Python instance (interpreter) for every request (like done in regular CGI, if I'm not mistaken), which is why I'm using FastCGI.

  • Following Lighttpd's documentation, the following is the FastCGI part of my config file. The problem is that it always runs the /usr/local/bin/python-fcgi script for every *.py file, regardless of the content of that file:

    http://www.example.com/script.py [output=>] "python-fcgi: test"

    (regardless of the content of script.py)

  • I'm not interested in using any framework, but simply executing individual [web] scripts.

How can I make it act like PHP, executing any script in the WWW directory by requesting it's path?

/etc/lighttpd/conf.d/fastcgi.conf:

server.modules += ( "mod_fastcgi" )

index-file.names += ( "index.php" )

fastcgi.server = (
    ".php" => (
        "localhost" => ( 
            "bin-path" => "/usr/bin/php-cgi",
            "socket" => "/var/run/lighttpd/php-fastcgi.sock",
            "max-procs" => 4, # default value
            "bin-environment" => (
                "PHP_FCGI_CHILDREN" => "1", # default value
            ),
            "broken-scriptfilename" => "enable"
          )
    ),
    ".py" =>
    (
        "python-fcgi" =>
        (
         "socket" => "/var/run/lighttpd/fastcgi.python.socket",
         "bin-path" => "/usr/local/bin/python-fcgi",
         "check-local" => "disable",
         "max-procs" => 1,
        )
    )
)

/usr/local/bin/python-fcgi:

#!/usr/bin/python2

def myapp(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    return ['python-fcgi: test\n']

if __name__ == '__main__':
    from flup.server.fcgi import WSGIServer
    WSGIServer(myapp).run()

The PHP (FastCGI) interpreter was build to run PHP files in this way; i.e. it runs one script, then forgets all the internal state for it, and start again.

Python was not build for this.

You could try to build a solution on top of flup; you would __import__ the requested script and call a "handleRequest" function in it or similar.

You can "reload" a module to update it: https://stackoverflow.com/questions/437589/how-do-i-unload-reload-a-python-module

But you cannot unload modules, so memory usage will grow: https://stackoverflow.com/questions/3105801/unload-a-module-in-python