[Chicago] How do you troubleshoot cgi errors?

Ian Bicking ianb at colorstudy.com
Mon Jul 23 19:28:45 CEST 2007


David Rock wrote:
> * Ian Bicking <ianb at colorstudy.com> [2007-07-23 09:29]:
>> You can do something like this:
>>
>> class ReplStdOut(object):
>>      def __init__(self, *files):
>>          self.files = files
>>      def __getattr__(self, attr):
>>          def repl_method(*args, **kw):
>>              for f in self.files:
>>                  value = getattr(f, attr)(*args, **kw)
>>              return value
>>          return repl_method
>>
>> sys.stdout = ReplStdout(sys.stdout, open('output.log', 'a'))
> 
> For those that want to try this out, there is a small typo, but it does
> work (very well, btw).  Here is the fixed version:
> 
> class ReplStdOut(object):
>      def __init__(self, *files):
>          self.files = files
>      def __getattr__(self, attr):
>          def repl_method(*args, **kw):
>              for f in self.files:
>                  value = getattr(f, attr)(*args, **kw)
>              return value
>          return repl_method
> 
> sys.stdout = ReplStdOut(sys.stdout, open('output.log', 'a'))
> 
> 
> Ok, this is the kind of stuff that reminds me there is always something
> new to learn :-)
> 
> It looks like this does what I need it to, but what is it actually
> doing?  Best as I can tell, this is basically creating a "tee" for
> stdout, and looks like it could be to multiple files, not just stdout
> and a file, right?  The question I have now is _why_ does this work?

It's actually a tee for any kind of object.  Any method that is called 
gets called on all the sub-objects (self.files in this case).  It only 
returns the return value of the last object, but for files you write to 
there's no meaningful return values anyway.  Similarly it doesn't handle 
attributes, since it treats everything like a method.

The __getattr__ method is called when the object has no other attribute 
-- i.e., if you call obj.foo, then obj.__getattr__('foo') is called (if 
the object has a __getattr__ method, and no foo attribute).  When you 
call obj.foo(x), then obj.__getattr__('foo')(x) is called.

In ReplStdOut whenever you call obj.anything, you get a function back. 
When you call that function, it gets subobject.anything from every 
subobject, and calls that with the arguments you pass in.  The function 
it returns is called a "closure", because the function object remembers 
the value of "self" and "attr" even though they aren't explicit 
arguments to the function.  That's all a closure really is -- a function 
that remembers some extra values.

-- 
Ian Bicking : ianb at colorstudy.com : http://blog.ianbicking.org
             : Write code, do good : http://topp.openplans.org/careers


More information about the Chicago mailing list