How to explain Django/Python installation to Python-newbie running a shared IIS server [closed]

For reasons beyond my control, our website is hosted with a hosting provider that uses IIS for their servers. They currently offer PHP and ASP, and also Python and Perl through cgi-scripts.

I want to do a re-design, re-write of our website, and want to change from PHP to a Python/Django setup. The hosting provider is open for suggestions, but are clear that "We don't really know what Python is, or how it works, but if you can explain it to us, we'll try to set you up with whatever you need".

However, I might know how to set up Django in a shared hosting environment on apache/mod_python, but I have no clue how it would be set up on IIS, and certainly not how it would be set up for a shared hosting environment. I've googled a bit, but most of the resources I find assume that the sysadmin 1) knows Python/Django and 2) is using dedicated IIS hosting for his site.

Could someone explain how I can explain the process to my hosting provider, or give me pointers to good, detailed resources I can forward to my hosting provider? Keep in mind that the people running the hosting might know "everything" about IIS, but have no idea how to deal with Python.


Solution 1:

If you're stuck with using IIS, use PyISAPIe instead of CGI if you can. Instructions and links for PyISAPIe are below. Your web host will know a lot more about ISAPI extensions if they manage IIS than about Python, and they don't need to know much about Python with PyISAPIe.

A MUCH BETTER WAY OF DOING THIS IS USING PyISAPIe, AN ISAPI EXTENSION. PyISAPIe is much, much faster than CGI on IIS7. What this does is similar to mod_python on Apache. The PyISAPIe project homepage has instructions for setting up Django with WSGI over PyISAPIe. This will bring your performance up to reasonable speeds for a public/high traffic website.

  • http://apps.sourceforge.net/trac/pyisapie/
  • http://pypi.python.org/pypi/PyISAPIe/

Setting up Django in an IIS+Python via CGI environment is going to be horribly slow for any production use. You should never use this for a website on which you expect to service more than a handful of requests per minute. It also limits you severely in what you can cache in memory in Django's caching framework, since the Django app's process is restarted with each new request.

In a sane web server like Apache, lighttpd, etc., with mod_python, the Python interpreter running the Django process remains in memory and is initialized with each new Apache worker thread that handles many requests over the course of time. This means that Python + Django are not exited and restarted for each new request. In a FastCGI setup, the web server (Apache or lighttpd for example) creates a socket (UNIX domain or TCP) across which it communicates with a FastCGI application (your Django web application) over the FastCGI protocol. Ditto for HTTP proxy setups (they speak HTTP instead of FastCGI). In a CGI environment, the Python interpreter is called which runs the Django application, completely anew for each request, so the application can not keep state across requests in memory and can't cache properly anywhere but in a database.

Enough ranting, if you must use IIS+CGI+Django, here's how to accomplish this horrible horrible thing: Use the following code to create your own CGI script which runs your Django app (it translates between CGI and WSGI). You'll have to edit the script a little to make it point to your Django app and code. That is the CGI script you would need to pass requests to. Next, you need to forward/rewrite all requests to your CGI script...

Under IIS6, you'll need a mod_rewrite equivalent like IISRewrite, which I think is not free and is closed source. Under IIS7, Microsoft finally included a URL rewriting module. Documentation for it is located here. Instructions for creating rewrite rules in IIS7 are here. You will want to forward everything at the target base URL to be handled by your CGI script.

  • http://code.djangoproject.com/attachment/ticket/2407/django.cgi
  • http://learn.iis.net/page.aspx/460/using-url-rewrite-module/
  • http://learn.iis.net/page.aspx/461/creating-rewrite-rules-for-the-url-rewrite-module/
  • http://apps.sourceforge.net/trac/pyisapie/
  • http://pypi.python.org/pypi/PyISAPIe/

Solution 2:

How to set up Python on FastCGI on IIS

Here's how to set up Python on FastCGI IIS 7+ with opens the way for a decent DJango setup

... and be able to hook a debugger into the process enabling you to step through your Python code

This example doesn't use the IIS management console but lists the contents of the resulting configuration files

Step 1

Install Python + a good debugger (this example uses WingIDE which I found an excellent tool) This example assumes folder c:\python27

Step 2

Create a web folder, eg on localhost c:\inetpub\wwwroot\mypythonfolder and put the following web.config file in it:

Note the | pipe character in the scriptProcessor directive. This is used by IIS to map the script to a fastCgi application (step 3). It should match character by character the fullpath + pipe character + arguments settings from step 3 below.

Step 3

In the applicationHost.config file in c:\windows\system32\inetsrc\config folder place the following in the section:

    <fastCgi>
        <application fullPath="c:\python27\python.exe" arguments="c:\python27\lib\mylib\myfcgi.py" monitorChangesTo="C:\Python27\Lib\r4a\r4afcgi.py" stderrMode="ReturnStdErrIn500" maxInstances="4" idleTimeout="300" activityTimeout="300" requestTimeout="90" instanceMaxRequests="200" protocol="NamedPipe" queueLength="1000" flushNamedPipe="true" rapidFailsPerMinute="10" />
    </fastCgi>

Step 4

In c:\python27\lib\mylib\myfcgi.py put the following code:

import wingdbstub

import os, io, sys ret = "environment:\r\n" for param in os.environ.keys(): ret = ret + "%s=%s\r\n" % (param,os.environ[param]) ret = ret + "\r\nArgs:" for arg in sys.argv: ret = ret + arg handle = io.open("c:\temp\myfcgi.log", 'wb') handle.write(ret) handle.close()

Step 5

Make sure IUSR has rights to write into your c:\temp folder

Step 6

Put wingdbstub.py and wingdebugpw into your c:\python27\lib\mylib\ folder. This will enable debugging in wingide. These files are provided with your wing installation. Note: if Python also needs to compile your code into wingstub.pyc, IUSR needs write rights on that folder since the python process will be launched under that account by IIS

Step 6

Open wingdb and set a breakpoint on the 'import os, io, sys' line

Step 7

Hit in your browser http://localhost/mypythonfolder

If everything works correct, wingide should now be triggered to display the running code at your breakpoint. If not: - either there's a firewall issue. The python process communicates with the WingIDE interface through a tcp connection - or there's an issue with security within wingide. It needs the proper version of the wingdebugpw file, which basically contains a password or token that validates access against your wingide installation. If this were not the case, anybody with tcp access to your pc could debug against your code.

Step 8

Verify that in c:\temp the logfile is created. This should also work if you can't get step 7 going

Step 9

Note that this page triggers the debugger but does not return any page to the webbrowser. Some background: the webserver communicates fastcgi through so called 'records'. This means that each single user-request comes into your application packed in multiple separate 'records'. Each record is a data structure that indicates the beginning of a request, the querystring, post variables etc. The un-packing of these records to a single request is kind of cumbersome, it follows the fastcgi specification of http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S1

As the content of c:\python27\lib\mylib\myfcgi.py I just dropped in a copy of zoofcgi.py provided by helicontech. This python file is able to decode these records and serve a page and is quite interesting to debug. Also note that helicontech optionally provides a dll that sits in between IIS and and zoofcgi.py but this dll is not strictly necessary. I believe it implements a slightly improved and generic version of the fastcgi implementation that msft provides. However when you use their dll, when you want to step through your code the process is terminated rather quicly and IIS/the DLL kills your python process when it concludes no response is coming back within a sec or 2.

That's it. In principle the communication between IIS and your python code is done with named pipes. You should be able to set it up using tcp sockets but I wasn't able to figure out which port is used (I believe the stdin should be transformed into the port which then can be select() ed but I didn't give that any attempt)