[python-win32] ASP Python

Jim Abrams Jim Abrams <jabrams@publishingresources.com>
Tue, 10 Jul 2001 10:12:55 -0400


Hello

MM> Do people do serious ASP programming in Python?  I've recently been
MM> doing somewhat-serious ASP programming in Perl and have started
MM> investigating Python as an alternative.  The lack of thorough
MM> documentation and reasonable examples struck me, but that didn't stop me
MM> from entering the Perl ASP world :-).  Anyway, I've got two questions
MM> that maybe someone can help me with.

I do all my serious ASP programming in Python.

MM> The first question deals with assigning to COM object properties which
MM> take arguments.  A very similar question was asked in April by Gregory
MM> P. Smith ("assigning vb properties from python via COM").  Consider the
MM> following piece of JScript code:
 
MM>  // example JScript code
MM>  Application('x') = 4;
MM>  Response.Write(Application('x'));
 
MM> The output is "4".  This example doesn't compile in python-land; you get
MM> an error because you're assigning to the result of a function call.  I
MM> think there was some confusion on the other thread, so let me just
MM> expand on what's happening here: JScript is calling the default method
MM> on the application object, "Value", so this is equivalent to the
MM> following JScript code:


MM>  // example JScript code
MM>  Application.Value('x') = 4;
MM>  Response.Write(Application('x'));

MM> JScript actually turns the assignment into a single COM call which is
MM> equivalent to this pseudo-C++ code:
 
MM>  // equivalent pseudo-C++ code
MM>  VARIANT v = { 0 };   // put “4” inside a variant
MM>  v.vt      = VT_I4;
MM>  v.lval    = 4;
 
MM>  BSTR  bstrPropName = SysAllocString(“x”);
 
MM>  // assume pApplication is of type IApplicationObject (see asp.dll)
MM>  pApplication->put_Value(bstrPropName, v);
 
MM>  SysFreeString(bstrPropName);

MM> Anyway, Perl doesn’t have as sophisticated IDispatch integration as
MM> Jscript does and cannot recognize something that looks like an
MM> assignment to the result of a function call as a property put to the COM
MM> object in question.  So the Perl guys have this hack workaround which
MM> works great (though it’s not terribly pretty): they implement a method
MM> on their COM objects called “SetProperty”:
 
MM>  # equivalent Perl code:
MM>  $Application->SetProperty('Value', 'x', 4);
MM>  $Response->Write($Application->Value('x'));
 
MM> Which brings me back to Python.  I haven’t been able to find anything
MM> similar in Python.  Fortunately, Python’s COM integration has much more
MM> to it than Perl’s, so I can call the IDispatch directly and do what I
MM> want.
 
MM>  # equivalent Python code:
MM>  o      = Application._oleobj_;
MM>  dispId = o.GetIDsOfNames('Value');
 
MM>  # perform the equivalent of Application('x') = 4
MM>  o.Invoke(dispId, 0x0, pythoncom.DISPATCH_PROPERTYPUT, 0, 'x', 4);
 
MM>  Response.Write(Application('x'));
 
MM> Blech!  Does anyone know a better way?

Application.SetValue('x', 4)
Session.SetValue('x', 4)

I wrote a simple wrapper for each that maps __setitem__ to SetValue
and makes things feel and look a touch better.

MM> Being able to store stuff in the application object, by the way, is
MM> really useful for ASP programming (at least the stuff I’m working on).
MM> It allows you to maintain a state across your web application from
MM> request to request.  The caveat is that anything you want to store in
MM> the Application object has to be able to fit inside a VARIANT.

Which, to my dislike, means no dictionaries. Although a quick
dict.items() can go in, and mx.Tools has a function called dict()
which will take the items() list and rebuild a dictionary at C-level
speed.

MM> Futhermore, if the thingy you want to store is an object (like
MM> VT_DISPATCH), then it has to be free-threaded (I’m not so sure about
MM> this restriction).  This is a bummer, because I would like to store Perl
MM> or Python’s rich data structures in there.

You can build Python COM objects and store them in Session and
Application.

MM> However, I was playing around with Python and noticed something strange.
MM> Consider the following ASP script:
 
MM>  <%@ LANGUAGE="Python" %>
MM>  <%
MM>  import sys;
MM>  if 'x' in dir(sys):
MM>     Response.Write('x in dir %s' % sys.x);
MM>     sys.x = sys.x + 1
MM>  else:
MM>     Response.Write('x not in dir');
MM>     sys.x = 0
MM>  %>
 
MM> What happens on my server setup is cool: “sys.x” is a counter of how
MM> many times I’ve refreshed the page.  Anyone know what’s going on here?
MM> I have a hunch this is just an implementation side-effect and not
MM> by-design, but it would be really useful.

The Python ASP engine caches the modules, so sys.x is actually
shared (Application scope). This also has the side effect that if you
want to get print to work, you could sys.stdout = SomeObject(Response)
that maps to Response.Write, however this won't work since its
Application-scope shared, and Response is page-level scope.
I ended up doing print >> _out, my stuff, and did:

from win32com.axscript.client.framework import SafeOutput
_out = SafeOutput(Response)

A couple more Python-ASP weirdisms.
Response.End() doesn't work, Response.end() does. (normally all the
other methods are capital, Response.Write, Server.MapPath, etc)

Modules are cached, and the mechanism for noticing newer files doesn't
work quite like regular python. You need to explicitly reload any
modules that you're using after you change them. I created a
reload.asp page where I keep all my reload statements.

Check out the HTMLgen library, it does wonders for correcting the
problem of html-inside code blocks.
I.E
if sys.x > 5:
   %><img src=5.gif><%
else:
   %><img src=lessthan5.gif><%

This doesn't work.

Also, some strange calls don't return what you expect.
objCN = Server.CreateObject("ADODB.Connection")
objCN.open(dsn)
objRS = objCN.Execute("select * etc")
objRS now has a tuple of (<RecordSetObject>, int)
I have no idea what the int means, but you need to trim it away to get
at the RecordSet object.

This has happened in some other places as well with 3rd party
COM-objects.

MM> I’m not subscribed to this list, so please copy me in any replies.
MM> Thanks in advance!
MM> Marc Miller

Hope this helped somewhat.

-- 
Jim Abrams
Sr. Software Engineer
Publishing Resources, Inc.
732.548.4609x22
jabrams@publishingresources.com