From: Gabriel Genellina on
En Thu, 17 Jun 2010 07:12:23 -0300, Fuzzyman <fuzzyman(a)gmail.com> escribi�:
> On Jun 17, 10:29 am, "Gabriel Genellina" <gagsl-...(a)yahoo.com.ar>
> wrote:
>> En Thu, 17 Jun 2010 04:52:48 -0300, Alf P. Steinbach <al...(a)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

From: Gabriel Genellina on
En Thu, 17 Jun 2010 14:09:38 -0300, John Nagle <nagle(a)animats.com>
escribi�:

> I'm trying out a proof of concept implementation for a new
> approach to safe threading. It's somewhat similar in concept
> to Alan Olsen's scheme. The basic difference is that once
> the program goes multi-thread, code objects and some other
> bindings are locked down and become unchangeable. Olsen
> was climbing the walls trying to get the locking right for
> the awful cases like redefining a function while another thread
> is inside it. I'm trying to lock out some of those cases.
> If you do that, removing the GIL requires less pain than
> Olsen experienced.
>
> The key idea is that the use cases for most of Python's
> code dynamism are during setup and initialization. You usually
> don't change code once the program has gone into its heavy
> parallel processing phase. This suggests a practical compromise.

Seems interesting...!

--
Gabriel Genellina

From: Fuzzyman on
On Jun 18, 5:25 am, "Gabriel Genellina" <gagsl-...(a)yahoo.com.ar>
wrote:
> En Thu, 17 Jun 2010 07:12:23 -0300, Fuzzyman <fuzzy...(a)gmail.com> escribi�:
>
> > On Jun 17, 10:29 am, "Gabriel Genellina" <gagsl-...(a)yahoo.com.ar>
> > wrote:
> >> En Thu, 17 Jun 2010 04:52:48 -0300, Alf P. Steinbach <al...(a)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.
>


Ah, so by "bypasses" you mean "under certain specific circumstances
bypasses". By all means file a bug report on this, I agree that
bypassing the optimization for file subclasses (assuming your
diagnosis is correct) would be a sensible approach.

All the best,

Michael


> --
> Gabriel Genellina