Redirect all stdout / stderr globally to logger

Background

I have a very large python application that runs command line utilities to get the pieces of data they need. I am currently just redirecting the python script startup program to a log file that gives me all the output print()as well as the output of the command line utilities, i.e.:

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

Problem

Since then, I have created the correct log using logging, which allows you to more accurately format the log statements, allows me to limit the size of the log file, etc. I've placed most of my operators print()with calls to my registrar. However, I have a problem: none of the application results from the command line appear in my log. Instead, it resets to the console. In addition, not all programs run the same way: some of them run through popen(), some - exec(), some - os.system()etc.


Question

stdout/stderr , / , ? , :

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

"sys.stderr.write ".

+4
2

, , . . , , , stdout stderr print(). :

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)
+1
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)

sys.stderr . sys.__stderr__

+1

Source: https://habr.com/ru/post/1692996/


All Articles