使用Python的“with”语句将stdout和stderr日志记录到日志文件中

5

我希望能够使用'with'语句将Python代码的标准输出记录到文件中:

with log_to_file('log'):
    # execute code

最简单的方法是手动定义log_to_file,例如:

import sys

class log_to_file():
    def __init__(self, filename):
        self.f = open(filename, 'wb')

    def __enter__(self):
        self.stdout = sys.stdout
        self.stderr = sys.stderr
        sys.stdout = self.f
        sys.stderr = self.f

    def __exit__(self, type, value, traceback):
        sys.stdout = self.stdout
        sys.stderr = self.stderr

或者是否已经有一个内置类可以完成这个任务?

请看这个问题。它似乎是你要找的。请注意,其中一个答案使用现有的logging模块,而其他答案使用multiprocessing。 - thegrinner
1
你的方法很好,即使你忘记在 __exit__ 中关闭文件 :) 我喜欢它。 - tito
1
你期望什么样的答案?我会以评论的形式给出:不,没有内置的类可以做到这一点。 - Ferdinand Beyer
好的。在类似的线路上,这里有一个用于测试的AssertPrints上下文管理器:https://github.com/ipython/ipython/blob/master/IPython/testing/tools.py#L342 - Thomas K
1个回答

2
我唯一能建议的是使用contextmanager装饰器,但我并不确定这是否真的更好。
from contextlib import contextmanager
@contextmanager
def stdouterrlog(logfile):
  with open(logfile, 'wb') as lf:
    stdout = sys.stdout
    stderr = sys.stderr
    sys.stdout = lf
    sys.stderr = lf
    yield lf  # support 'with stdouterrlog(x) as logfile'
    sys.stdout = stdout
    sys.stderr = stderr

为什么不使用 file 对象固有的上下文管理器呢?也就是说,将 stdouterrlog 的主体设为 with open(logfile, 'wb') as logfile: \n (do sys.stdout stuff...) \n yield logfile \n (undo sys.stdout stuff...)。 - detly
是的,这将节省一行额外的代码。 - wberry
1
除此之外,你可能还应该将整个代码块包裹在一个 try/finally 块中,否则未处理的错误会使日志文件保持打开状态。 - detly

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接