Monthly Archives: January 2013

自定义stdout

在python中, 有时候你需要捕捉print的输出保存到一个指定的文件下面. 一般的情况下, print实际上是调用的sys.stdout. 如果你需要需要对print进行捕捉. 你只要需要hook sys.stdout即可.

例如我们将所有的print都保存到StringIO下, 只需要写成

from StringIO import StringIO
import sys
old_stdout = sys.stdout
sys.stdout = mystdout = StringIO()

#获取内部值
sys.stdout = old_stdout
print mystdout.getvalue()
mystdout.close()

但是当你的print中有unicode字符的时, 使用StringIO会报TyperError或者UnicodeError之类的错误.这个时候我们需要进行一下改写.

from StringIO import StringIO
import sys, itertools

class Logger(object):
  def __init__(self):
    self.log = StringIO();
    self.terminal = sys.stdout

  def write(self, message):
    self.log.write(self.safestr(message))

  def safestr(self, obj, encoding='utf-8'):
    #包含能正确转换
    if isinstance(obj, unicode):
      return obj.encode(encoding)
    elif isinstance(obj, str):
      return obj
    elif hasattr(obj, 'next'):
      return itertools.imap(self.safestr, obj)
    else:
      return str(obj)

  def close(self):
    self.log.close()

  def output(self):
    self.terminal.write(self.log.getvalue())

old_stdout = sys.stdout
sys.stdout = Logger()

print "Hello"

print u"测试"

#将所有catch的输出到terminal
sys.stdout.output()

"""
Hello
测试
"""
sys.stdout.close()

在print调用write使用, 我们将message进行一次转码. 在通过调用StringIO().getvalue方法的时候, 就不会报错了.

如果你想将写入文件, 只需要在self.log这部分进行一下改动即可.

self.log = open("debug.log", "a")