views:

346

answers:

3

I have a small Python web application using the Cherrypy framework. I am by no means an expert in web servers.

I got Cherrypy working with Apache using mod_python on our Ubuntu server. This time, however, I have to use Windows 2003 and IIS 6.0 to host my site.

The site runs perfectly as a stand alone server - I am just so lost when it comes to getting IIS running. I have spent the past day Googling and blindly trying any and everything to get this running.

I have all the various tools installed that websites have told me to (Python 2.6, CherrpyPy 3, ISAPI-WSGI, PyWin32) and have read all the documentation I can. This blog was the most helpful:

http://whatschrisdoing.com/blog/2008/07/10/turbogears-isapi-wsgi-iis/

But I am still lost as to what I need to run my site. I can't find any thorough examples or how-to's to even start with. I hope someone here can help!

Cheers.

+6  A: 

I run CherryPy behind my IIS sites. There are several tricks to get it to work.

  1. When running as the IIS Worker Process identity, you won't have the same permissions as you do when you run the site from your user process. Things will break. In particular, anything that wants to write to the file system will probably not work without some tweaking.
  2. If you're using setuptools, you probably want to install your components with the -Z option (unzips all eggs).
  3. Use win32traceutil to track down problems. Be sure that in your hook script that you're importing win32traceutil. Then, when you're attempting to access the web site, if anything goes wrong, make sure it gets printed to standard out, it'll get logged to the trace utility. Use 'python -m win32traceutil' to see the output from the trace.

It's important to understand the basic process to get an ISAPI application running. I suggest first getting a hello-world WSGI application running under ISAPI_WSGI. Here's an early version of a hook script I used to validate that I was getting CherryPy to work with my web server.

#!python

"""
Things to remember:
easy_install munges permissions on zip eggs.
anything that's installed in a user folder (i.e. setup develop) will probably not work.
There may still exist an issue with static files.
"""


import sys
import os
import isapi_wsgi

# change this to '/myapp' to have the site installed to only a virtual
#  directory of the site.
site_root = '/'

if hasattr(sys, "isapidllhandle"):
 import win32traceutil

appdir = os.path.dirname(__file__)
egg_cache = os.path.join(appdir, 'egg-tmp')
if not os.path.exists(egg_cache):
 os.makedirs(egg_cache)
os.environ['PYTHON_EGG_CACHE'] = egg_cache
os.chdir(appdir)

import cherrypy
import traceback

class Root(object):
 @cherrypy.expose
 def index(self):
  return 'Hai Werld'

def setup_application():
 print "starting cherrypy application server"
 #app_root = os.path.dirname(__file__)
 #sys.path.append(app_root)
 app = cherrypy.tree.mount(Root(), site_root)
 print "successfully set up the application"
 return app

def __ExtensionFactory__():
 "The entry point for when the ISAPIDLL is triggered"
 try:
  # import the wsgi app creator
  app = setup_application()
  return isapi_wsgi.ISAPISimpleHandler(app)
 except:
  import traceback
  traceback.print_exc()
  f = open(os.path.join(appdir, 'critical error.txt'), 'w')
  traceback.print_exc(file=f)
  f.close()

def install_virtual_dir():
 import isapi.install
 params = isapi.install.ISAPIParameters()
 # Setup the virtual directories - this is a list of directories our
 # extension uses - in this case only 1.
 # Each extension has a "script map" - this is the mapping of ISAPI
 # extensions.
 sm = [
  isapi.install.ScriptMapParams(Extension="*", Flags=0)
 ]
 vd = isapi.install.VirtualDirParameters(
  Server="CherryPy Web Server",
  Name=site_root,
  Description = "CherryPy Application",
  ScriptMaps = sm,
  ScriptMapUpdate = "end",
  )
 params.VirtualDirs = [vd]
 isapi.install.HandleCommandLine(params)

if __name__=='__main__':
 # If run from the command-line, install ourselves.
 install_virtual_dir()

This script does several things. It (a) acts as the installer, installing itself into IIS [install_virtual_dir], (b) contains the entry point when IIS loads the DLL [__ExtensionFactory__], and (c) it creates the CherryPy WSGI instance consumed by the ISAPI handler [setup_application].

If you place this in your \inetpub\cherrypy directory and run it, it will attempt to install itself to the root of your IIS web site named "CherryPy Web Server".

You're also welcome to take a look at my production web site code, which has refactored all of this into different modules.

Jason R. Coombs
Hi Jason,Thank you for replying. I had to have the site running on Friday so sadly it is just running as a process using CherryPy.I will try out your tips later today. I got a Hello World to work (somewhat) using a lot of trial and error - will let you know how I get on.
Hamish
OK, so I tried using your example here and I have run into the same issue which I had with my own HelloWorld. I believe my IIS configuration is the issue, not my Python.When I try running your HelloWorld, I get an error with a long traceback ending with: <COMObject IIS://LocalHost/W3SVC/1015677672/ROOT>.I can, however, install it as a virtual directory (change the Name parameter). Unless I have an exposed method of the same name as the VD I get a CherryPy servered 404.I hate being such a newbie, but could you shed any light on how to set up the IIS site from the start?
Hamish
Double-check you're using isapi-wsgi 0.4.1. There was an issue with 0.4 where certain web sites won't be detected correctly (had to do with the case of /ROOT in the IIS site object).
Jason R. Coombs
As far as creating the IIS site is concerned, I normally just go into IIS manager and create a new web site called "CherryPy Web Server" with no special treatment. Specifically, I created the directory \inetpub\cherrypy, saved the above code as hook.py in that directory, ran 'hook.py install', and then browsed to the newly-created site, and it just worked.
Jason R. Coombs
The reason you're getting the 404 is because CherryPy does not implicitly remove any part of the path name that IIS hands to it. If you want to install the CherryPy app to anything other than the root, you need to change where CherryPy mounts to. I'll update the script to account for non-root installs.
Jason R. Coombs
I am using isapi-wsgi 0.4.1. I have been using the Windows binary installers for everything, however. I have been setting everything in the manner you mentioned (I don't know enough about IIS to dare touch the configurations) and it is still not working. Sigh!Still get the same error when I try to install the HelloWorld. I think I will remove all my Python modules and build them as you suggested and try again.
Hamish
Can you send a few more lines of the traceback?
Jason R. Coombs
+1  A: 

I'm using the answer so that I can post the traceback in a formatted way. When I copy your HelloWorld and run it from the data directory set up in IIS (with the names specified above) this is the Trackback:

Traceback (most recent call last):
  File "D:\PRS\HelloWorld\HelloWorld.py", line 76, in <module>
    install_virtual_dir()
  File "D:\PRS\HelloWorld\HelloWorld.py", line 72, in install_virtual_dir
    isapi.install.HandleCommandLine(params)
  File "C:\Python26\lib\site-packages\isapi\install.py", line 572, in HandleCommandLine
    InstallModule(conf_module_name, params, options)
  File "C:\Python26\lib\site-packages\isapi\install.py", line 494, in InstallModule
    Install(params, options)
  File "C:\Python26\lib\site-packages\isapi\install.py", line 401, in Install
    CreateDirectory(vd, options)
  File "C:\Python26\lib\site-packages\isapi\install.py", line 198, in CreateDirectory
    newDir = webDir.Create(keyType, name)
  File "<COMObject IIS://LocalHost/W3SVC/1015677672/ROOT>", line 2, in Create
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, None, None, None, 0, -2147463168), None)

Thank you for your continued help here, Jason. I hope we can get this sorted.

Hamish
The error being thrown is an E_ADS_BAD_PATHNAME which is strange.I changed it to install to a virtual directory 'a' and now it seems to be working. Very strange.
Hamish
I don't know why it isn't working for the root of the site, but it seems to be fine running in a virtual directory. Now I am facing issues with it not 'finding' the cherrypy.session function - which my code heavily relies on. I suppose that is another question!
Hamish
-2147352567 == 0x80020008 which indicates "Error: Bad variable type". I wonder if maybe the pywin32 package is out of date. I seem to recall back in build 212 or so there was a fix also for installing to a root of the site. It seems that it's trying to _create_ the root virtual directory, which should already exist. I suspect if you get pywin32-214 that will fix this issue.
Jason R. Coombs
I suspect the reason it doesn't find cherrypy.session is because you haven't turned on the session filter. See http://www.cherrypy.org/wiki/CherryPySessions for details.
Jason R. Coombs
Ah, I looked up the wrong Hex value - oops. I haven't looked into getting it to run at the root of the site, mainly because that is not a high priority (I think when it is deployed it will be in a Virtual Directory anyway). In my startup I am not specifying CherryPy to read my config file with the session and static info in it. So, now I will attempt to get it to read that. I am perusing your site to see if that has any clues. Cheers for your help thus far.
Hamish
I have added the following: app = cherrypy.tree.mount(Root(), site_root, config=config) to my setup_application() and have a simple write attribute to session in my HelloWorld. It is still giving me an AttributeError. The variable config is a valid configuration dict for CherryPy (it works when run stand-alone). I feel if getting sessions to run, I will be successful with getting CherryPy to run with IIS.
Hamish
+1  A: 

OK, I got it working. Thanks to Jason and all his help. I needed to call

cherrypy.config.update({
  'tools.sessions.on': True
})
return cherrypy.tree.mount(Root(), '/', config=path_to_config)

I had this in the config file under [/] but for some reason it did not like that. Now I can get my web app up and running - then I think I will try and work out why it needs that config update and doesn't like the config file I have...

Hamish