0

I recenlty desired a bit of python code that would allow me to output to the console and a logfile with the same print statement. After googleing I found this website which offered an excellent solution. However, I would like to be able to flush the output buffer after each write in order to see it in the log file. How would I go about adding it into this class?

I have tried to following setups...

class output_file(object):
  def __init__(self, stdout, filename):
    silentremove(filename)
    self.stdout = stdout
    self.logfile = open(filename, "a")

def write(self, text):
    self.stdout.write(text)
    self.logfile.write(text)
    sys.stdout.flush()

  def flush(self):
    sys.stdout.flush()

  def close(self):
    self.stdout.close()
    self.logfile.close()

This was had a cyclic error which resulted in the flush function calling itself.

class output_file(object):
  def __init__(self, stdout, filename):
    silentremove(filename)
    self.stdout = stdout
    self.logfile = open(filename, "a")

  def write(self, text):
    self.stdout.write(text)
    self.logfile.write(text)
    self.stdout.flush()

  def flush(self):
    sys.stdout.flush()

  def close(self):
    self.stdout.close()
    self.logfile.close()

This didn't flush it at all.

3
  • 4
    Not answering the question but you may want to look at the logging module. To do what you want to do, you can define two handlers (One for console and one for file) for the same logger Commented Feb 24, 2014 at 11:15
  • @RedBaron This is exactly what I was looking for originally. If you submit it as an answer I will accept it. Commented Feb 24, 2014 at 14:28
  • Technically it wasn't an answer to your question so won't be appropriate for me to post it. For future visitors, you can post an epilogue to your question explaining how logging helped you overcome your original problem (which led to this question) Commented Feb 25, 2014 at 4:21

1 Answer 1

4

The following reopens sys.stdout in unbuffered mode. Each stdout.write and print will be automatically flushed (i.e. printed to stdout) afterwards.

import sys
import os

# Flush STDOUT continuously
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

The third argument of os.fdopen is the buffering argument, 0 is unbuffered, 1 is line buffered and >1 will result in a buffer of (approximately) that size (in bytes), <0 will use the systems default.

UPDATE

With Python 3 unbuffered text is not allowed, i.e. the following

sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

Will result in the error

ValueError: Can't have unbuffered text I/O

To use unbuffered I/O in python3, bytes can be used, i.e.

sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)

Will work fine in python3.

Sign up to request clarification or add additional context in comments.

5 Comments

To later revert to the original behavior of sys.stdout: sys.stdout is still available as sys.__stdout__.
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1)
ValueError: can't have unbuffered text I/O
Thanks for the quick update. Was facing issue with this on idle and PyCharm..could resolve it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.