Overriding "__setattr__" of a module - possible?

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Fri Jun 18 00:25:04 EDT 2010


En Thu, 17 Jun 2010 07:12:23 -0300, Fuzzyman <fuzzyman at gmail.com> escribió:
> On Jun 17, 10:29 am, "Gabriel Genellina" <gagsl-... at yahoo.com.ar>
> wrote:
>> En Thu, 17 Jun 2010 04:52:48 -0300, Alf P. Steinbach <al... at start.no>  
>> escribió:
>>
>> > But who would have thunk that Python *isn't dynamic enough*? :-)
>>
>> Yep... There are other examples too (e.g. the print statement in 2.x  
>> bypasses sys.stdout.write;
>
> What do you mean by this? The print statement in 2.x does *not* bypass
> sys.stdout. It may use other methods besides write (writeln perhaps)
> but you can *definitely* override sys.stdout to capture the output
> from print statements.

Suppose you want to implement a "tee" variant in Python: print output
should go to stdout and also to some file (with timestamp added, just to
be fancy). First attempt:

py> import sys
py> import time
py>
py> class tee(file):
...   def write(self, data):
...     file.write(self, '%s: %r\n' % (time.ctime(), data))
...     sys.__stdout__.write(data)
...
py> sys.stdout = tee('test.txt', 'w')
py> print "Hello world"
py> print "Bye"
py> ^Z

D:\TEMP>type test.txt
Hello world
Bye


Note:
- no output to stdout inside the interpreter
- no timestamp in the file

This modified version works fine:

py> class tee():
...   def __init__(self, filename, mode):
...     self.file = open(filename, mode)
...   def write(self, data):
...     self.file.write('%s: %r\n' % (time.ctime(), data))
...     sys.__stdout__.write(data)

What happened? When sys.stdout is an instance of some class inheriting
   from file (that is, isinstance(sys.stdout, file) is true) then the print
statement ignores sys.stdout.write() completely -- instead it calls
directly some C stdio functions (fwrite).
The only way to influence 'print' is *not* to inherit from file in the
first place.

It's an optimization, sure.  I guess it is there before inheriting from
builtin types was allowed (in such scenario, it's a perfectly valid
optimization).  Now, perhaps the test for 'file' should be more strict,
only taking the C shortcut when using an actual file instance, not a
subclass of it.  This would allow the example above to work correctly.

-- 
Gabriel Genellina




More information about the Python-list mailing list