简体   繁体   English

将所有stdout / stderr全局重定向到记录器

[英]Redirect all stdout/stderr globally to logger

Background 背景

I have a very large python application that launches command-line utilities to get pieces of data it needs. 我有一个非常大的python应用程序,它启动命令行实用程序来获取所需的数据。 I currently just redirect the python launcher script to a log file, which gives me all of the print() output, plus the output of the command-line utilities, ie: 我目前只是将python启动程序脚本重定向到一个日志文件,它给了我所有的print()输出,以及命令行实用程序的输出,即:

python -m launcher.py &> /root/out.log

Problem 问题

I've since implemented a proper logger via logging , which lets me format the logging statements more precisely, lets me limit log file size, etc. I've swapped out most of my print() statements with calls to my logger. 我已经通过logging实现了一个合适的记录器,这使我可以更精确地格式化日志记录语句,让我限制日志文件大小等。我已经通过调用我的记录器来换掉大部分的print()语句。 However, I have a problem: none of the output from the command-line applications is appearing in my log. 但是,我遇到了一个问题:命令行应用程序的输出都没有出现在我的日志中。 It instead gets dumped to the console. 它反而被转储到控制台。 Also, the programs aren't all launched the same way: some are launched via popen() , some by exec() , some by os.system() , etc. 此外,程序并非都以相同的方式启动:一些通过popen()启动,一些通过exec() ,一些通过os.system()


Question

Is there a way to globally redirect all stdout / stderr text to my logging function, without having to re-write/modify the code that launches these command-line tools? 有没有办法将所有stdout / stderr文本全局重定向到我的日志记录功能,而无需重新编写/修改启动这些命令行工具的代码? I tried setting setting the following which I found in another question: 我尝试设置以下我在另一个问题中找到的设置:

sys.stderr.write = lambda s: logger.error(s)

However it fails with " sys.stderr.write is read-only". 但它失败了“ sys.stderr.write是只读的”。

While this is not a full answer, it may show you a redirect to adapt to your particular case. 虽然这不是一个完整的答案,但它可能会向您显示重定向以适应您的特定情况。 This is how I did it a while back. 这是我一段时间做的。 Although I cannot remember why I did it this way, or what the limitation was I was trying to circumvent, the following is redirecting stdout and stderr to a class for print() statements. 虽然我不记得为什么我这样做了,或者我试图规避的限制是什么,以下是将stdoutstderr重定向到print()语句的类。 The class subsequently writes to screen and to file: 该类随后写入屏幕和文件:

import os
import sys
import datetime

class DebugLogger():

    def __init__(self, filename):
        timestamp = datetime.datetime.strftime(datetime.datetime.utcnow(), 
                                               '%Y-%m-%d-%H-%M-%S-%f')
        #build up full path to filename
        logfile = os.path.join(os.path.dirname(sys.executable), 
                               filename + timestamp)
        self.terminal = sys.stdout
        self.log = open(logfile, 'a')

    def write(self, message):
        timestamp = datetime.datetime.strftime(datetime.datetime.utcnow(), 
                                               ' %Y-%m-%d-%H:%M:%S.%f')
        #write to screen
        self.terminal.write(message)
        #write to file
        self.log.write(timestamp + ' - ' + message)      
        self.flush()

    def flush(self):
        self.terminal.flush()
        self.log.flush()
        os.fsync(self.log.fileno())

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


def main(debug = False):
    if debug:
        filename = 'blabla'
        sys.stdout = DebugLogger(filename)
        sys.stderr = sys.stdout
    print('test')

if __name__ == '__main__':
    main(debug = True)
import sys
import io

class MyStream(io.IOBase):
    def write(self, s):
        logger.error(s)

sys.stderr = MyStream()

print('This is an error', stream=sys.stderr)

This make all call to sys.stderr go to the logger. 这使得对sys.stderr所有调用都转到了记录器。 The original one is always in sys.__stderr__ 原始的一个总是在sys.__stderr__

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM