8

I need to output all my print statements to both terminal and file. I've found a solution in this stackoverflow question So i use

class Tee(object): 
    def __init__(self, name): 
        self.file = open(name, "a") 
        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)

sys.stdout = Tee("log.txt")

That's works great ,

My problem is when i want to stop writing to file and go back to normal operation that's print only to terminal
I tried to use del(sys.stdout) to invoke the del method with no luck.
i even tried to change the last line to:

    multiple_print = Tee("log.txt")
    sys.stdout = multiple_print

and than use del(multiple_print) and failed

No matter what i tried , further uses of print still written to terminal and file both.

Any ideas?

Community
  • 1
  • 1
Gil.I
  • 895
  • 12
  • 23

1 Answers1

18

You need to save a reference to the original file-descriptor before reassignment:

oldstdout = sys.stdout

and afterwards reassign it to sys.stdout!

The del statement doesn't call __del__ directly, but rather decreases the reference counter of your object. the __del__ method is called if the reference counter reaches zero and your object is about to get destroyed. So you can't force the reassignment, because it's up to the garbage collector, to call your __del__ method.

You need to directly reassign the sys.stdout variable:

Try:

sys.stdout = sys.__stdout__
Don Question
  • 11,227
  • 5
  • 36
  • 54
  • Thanks. I try to make the complicated solution to work and forgot the basic. However , do you know why the __del__ is not working? (it contains sys.stdout = self.stdout that is saved in the __init__ part) – Gil.I Jan 08 '12 at 11:52
  • 15
    Note you can also use [sys.__stdout__](http://docs.python.org/library/sys.html#sys.__stdout__) instead of storing the old reference yourself. – Frédéric Hamidi Jan 08 '12 at 11:53
  • 1
    i updated my answer to address your follow-ups! And Frederic Hamidi has a point! I didn't know about `sys.__stdout__`! – Don Question Jan 08 '12 at 11:56
  • 1
    sys.stdout = multiple_print.stdout is not working but oldstdout=sys.stdout or sys.stdout = sys.__stdout__ are good solutions – Gil.I Jan 08 '12 at 12:04