feik
feik

Reputation: 387

Python Stdout redirect from IDLE

I am trying to get the following code to work for the terminal and the IDLE shell. It is intended to split the stdout to the screen and a log file.

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

Tee('logfile.log', 'wb')

print 'test123'

If I run this code from the terminal it works fine. If I execute it from IDLE it prints as it should, but there is no text in the log file and no exceptions are thrown. Why does this work from the command promt but not IDLE? What can I do to make it work in both environments? I'm on Win7 and Python 2.7.

Edit: I put this together to work for with statements. Its my first crack at a with class, so suggestions for improvement are welcome.

newlog = True
class Tee(object):
    def __init__(self, name, mode=''):
        global newlog
        if newlog:
            self.filename = open(name, 'w'+mode)
        else:
            self.filename = open(name, 'a'+mode)
        newlog = False
    def __enter__(self):
        self.stdout = sys.stdout
        sys.stdout = self
        return self
    def __exit__(self, name, mode, data):
        sys.stdout = self.stdout
        self.filename.close()
    def __del__(self):
        try:
            self.filename.close()
            sys.stdout = self.stdout
        except:
            pass
    def startlog(self):
       self.stdout = sys.stdout
       sys.stdout = self
    def stoplog(self):
        self.filename.close()
        sys.stdout = self.stdout 
    def write(self, data):
        self.stdout.write(data)
        self.filename.write(data)
        self.filename.flush()


with Tee('logfile.log', 'b'):
    print 'I am the walrus'

print 'coocoocachoo'

Tee = Tee('logfile.log')
Tee.startlog()
print 'I am the eggman'
Tee.stoplog()

print 'coocoocachoo'

Upvotes: 1

Views: 1160

Answers (1)

itai
itai

Reputation: 1606

logfile.log is not empty, its just not getting flushed. try:

sys.stdout.filename.flush()

What you can do is just write a fuller wrapper. Idea - you could even do this in a more generic way, something in the likes of (there might be be a few issues to solve here):

import functools
class Tee(object):
    def __init__(self, name, mode)
    .
    .
    for name in ('write', 'flush', ...):
        setattr(self, name, functools.partial(self._wrapper, name))

    def _wrapper(func_name, *args, **kw):
        getattr(self.filename, name)(*args, **kw)
        getattr(self.stdout, name)(*args, **kw)

Upvotes: 2

Related Questions