Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

Python Programming Language

Issue of redirecting the stdout to both file and screen


I wanna print the log to both the screen and file, so I simulatered a
'tee'

class Tee(file):

    def __init__(self, name, mode):
        file.__init__(self, name, mode)
        self.stdout = sys.stdout
        sys.stdout = self

    def __del__(self):
        sys.stdout = self.stdout
        self.close()

    def write(self, data):
        file.write(self, data)
        self.stdout.write(data)

Tee('logfile', 'w')
print >>sys.stdout, 'abcdefg'

I found that it only output to the file, nothing to screen. Why?
It seems the 'write' function was not called when I *print* something.

There are places in the C code of Python that do the equivalent of

if isinstance(file_like_object, file):
    file.write(file_like_object, text)
else:
    file_like_object.write(text)

Therefore you can't safely inherit from file. The workaround is to make your
own file-like object; yours would become

class Tee(object):
    def __init__(self, name, mode):
        self.file = open(name, mode)
        self.stdout = sys.stdout
        sys.stdout = self
    def __del__(self):
        sys.stdout = self.stdout
        self.file.close()
    def write(self, data):
        self.file.write(data)
        self.stdout.write(data)

Peter

En Mon, 28 May 2007 06:17:39 -0300,  
<kelvin.@gmail.com> escribi:

You create a Tee instance and it is immediately garbage collected. I'd  
restore sys.stdout on Tee.close, not __del__ (you forgot to call the  
inherited __del__ method, btw).
Mmm, doesn't work. I think there is an optimization somewhere: if it looks  
like a real file object, it uses the original file write method, not yours.
The trick would be to use an object that does NOT inherit from file:

import sys
class TeeNoFile(object):
     def __init__(self, name, mode):
         self.file = open(name, mode)
         self.stdout = sys.stdout
         sys.stdout = self
     def close(self):
         if self.stdout is not None:
             sys.stdout = self.stdout
             self.stdout = None
         if self.file is not None:
             self.file.close()
             self.file = None
     def write(self, data):
         self.file.write(data)
         self.stdout.write(data)
     def flush(self):
         self.file.flush()
         self.stdout.flush()
     def __del__(self):
         self.close()

tee=TeeNoFile('logfile', 'w')
print 'abcdefg'
print 'another line'
tee.close()
print 'screen only'
del tee # should do nothing

--
Gabriel Genellina

It is not garbage collected until the next assignment to sys.stdout.

Peter

En Mon, 28 May 2007 09:10:40 -0300, Peter Otten <__pete@web.de>  
escribi:

Yes, sorry, this was my first guess. Later I discovered the real reason  
-you pointed it too-, I should have removed the whole first paragraph on  
my reply.

--
Gabriel Genellina

I see. Many thanks to you!
Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc