|
|
 |
 |
 |
 |
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.
wrote: > 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:
> 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.
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
Gabriel Genellina wrote: > En Mon, 28 May 2007 06:17:39 -0300, ??????????????? > <kelvin. @gmail.com> escribi: >> 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. > You create a Tee instance and it is immediately garbage collected.
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:
> Gabriel Genellina wrote: >> En Mon, 28 May 2007 06:17:39 -0300, ??????????????? >> <kelvin.@gmail.com> escribi: >>> def __init__(self, name, mode): >>> file.__init__(self, name, mode) >>> self.stdout = sys.stdout >>> sys.stdout = self >>> 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. >> You create a Tee instance and it is immediately garbage collected. > It is not garbage collected until the next assignment to sys.stdout.
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!
|
 |
 |
 |
 |
|