4

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.

pavium
  • 14,808
  • 4
  • 33
  • 50
hsimah
  • 1,265
  • 2
  • 20
  • 37
  • When you got cherrypy working *with* apache, did you have to bind it to a different port (eg, 8080) to avoid conflict with apache, or was it something more subtle? I ask because cherrypy can do stand-alone websites and doesn't *need* apache. – pavium Nov 05 '09 at 01:57
  • I bound it to port 80 in Apache. You can make the stand-alone Cherrypy host listen on port 80 (or any other) if you desire, too. – hsimah Nov 05 '09 at 03:29
  • Port numbers don't matter. When you're using ISAPI-wsgi, the WSGI application is called natively from the web server process (loaded by a DLL), so the only relevant port number is the one configured in IIS. – Jason R. Coombs Nov 05 '09 at 13:52

2 Answers2

10

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
  • 41,115
  • 10
  • 83
  • 93
  • 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. – hsimah Nov 08 '09 at 23:24
  • 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: . 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? – hsimah Nov 09 '09 at 00:06
  • 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 Nov 09 '09 at 14:49
  • 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 Nov 09 '09 at 15:07
  • 1
    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 Nov 09 '09 at 15:11
  • 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. – hsimah Nov 09 '09 at 23:45
  • Can you send a few more lines of the traceback? – Jason R. Coombs Nov 10 '09 at 12:51
2

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...

hsimah
  • 1,265
  • 2
  • 20
  • 37