Greetings! I am using Apache 2.2.25, Mod WSGI 3.3, LXML 3.2.1, and Python 2.7.2 My web site scheme stores web pages as XML documents which are transformed into XHTML on-the-fly using XSLT. Previously I had been using a mod_python output filter and I am now trying to update my system to use mod_wsgi. I have converted the mod_python output filter into an equivalent mod_wsgi script as shown below. This script when run outside of mod_wsgi functions perfectly. When it is run inside mod_wsgi it goes into the etree.XSLT() method on line 57 and there it hangs up until Apache times out the request. No information is written to the errorlog files. I have gone through all the known application issues and debugging suggestions given on the mod_wsgi wikki to no avail. Any help at this point would be greatly appreciated. """ Transform an XML document into an XHTML document """ import sys, os, time from cStringIO import StringIO sys.path.append('C:/webroot/sites/wsgitest/wsgiscripts') sys.path.append('C:/webroot/sites/wsgitest/content') sys.path.append('C:/Python27/lib/site-packages/lxml') from lxml import etree from fileutils import * from nsutils import * ns = {'pysite': 'http://www.leebrown.org/pysite'} def paramify (parent, target={}): """ A very quick and dirty objectification function. Given an arbitrary parent etree element, creates a dictionary of {local-name:text} from each child element. Also adds necessary embedded quotes to make the dictionary suitable to pass as XSLT parameters. Requires function lname() from module nsutils.py """ for child in parent.getchildren(): target[lname(child.tag)] = "'%s'" % (child.text) return target def parse_source (streambuffer): """ Converts the source XML held in streambuffer into an lxml Element Tree. Source includes are also processed at this time. """ streambuffer.seek(0) xml_tree = etree.parse(streambuffer, etree.XMLParser(remove_blank_text=True)) xml_tree.xinclude() return xml_tree def parse_template (xml_tree): """ Attempts to create an XSLT transform object from an xml-stylesheet PI in the source tree. Returns a None object if no xml-stylesheet PI is found; this causes the transform() function below to return untransformed XML to the client. """ xsl_pi = xml_tree.getroot().getprevious() xsl_tree = xsl_pi.parseXSL() if xsl_tree: return etree.XSLT(xsl_tree) else: return None def get_params (xml_tree): """ If the source XML contains a <page-params> element in the target namespace, convert all child elements of this element into an XLST parameter dictionary. Other parameters may be added on as desired. """ try: params = paramify(xml_tree.xpath('//pysite:page-params', namespaces=ns)[0]) except IndexError: params = {} return params def transform (streambuffer): """ This is where most of the fun stuff happens. If parse_template() returns a transformer object, the source XML tree is transformed, and any xincludes added in the transform are then processed. If parse template() does not return a tranformer object, this function returns the unparsed, untransformed XML source. """ xml_tree = parse_source(streambuffer) transformer = parse_template(xml_tree) if transformer: params = get_params(xml_tree) result_tree = transformer(xml_tree, **params) result_tree.xinclude() return result_tree else: return streambuffer.getvalue() def parse_request(environ): path = environ['PATH_INFO'].lstrip('/') filespec = smoothpath('C:/webroot/sites/wsgitest/content', path, 'page.xml') return filespec def application(environ,start_response): start = time.clock() buffer = StringIO() try: buffer.write(readfile(parse_request(environ))) result_tree = transform(buffer) end = time.clock() try: # Looks for %f and %i in output, inserts transform time # and pages per second if found result = str(result_tree) % (float(end - start), int(1.0/(end - start))) except: result = str(result_tree) status = '200 OK' except IOError: status = '404 FILE NOT FOUND' result = '404 FILE NOT FOUND' finally: # Prepare HTTP response response_headers = [('Content-Type','text/html'),('Content-Length',str(len(result)))] start_response(status,response_headers) return([result]) if __name__ == '__main__': def start_response(status, response_headers): pass environ = {} environ['PATH_INFO'] = '/' result = application(environ, start_response) for line in result: print line -- Best Regards, Lee E. Brown