【问题标题】:Disable Format for some messages禁用某些消息的格式
【发布时间】:2016-04-29 12:08:30
【问题描述】:

我正在使用 pythons 日志库开发数据分析管道。我正在记录有关正在运行的步骤的自定义消息以及调用程序的原始输出。我使用sh.py 来简化shell 命令的调用。它让我可以定义一个回调函数来处理STDOUT/STDERR 的每一行。

我希望能够定义我的回调函数以将每一行记录到日志文件中而不需要格式化(这些程序输出很多行):

log.info("Starting %s run on %s", program_name, file_name)

def call_back(line):
    log.info.NOFORMAT(line)  # do the no format logging

sh.program(args, _out=call_back)

log.info("Finished running %s", program_name)

我生成的日志文件将如下所示:

"""<br>
2016-01-22|{INFO}: Starting $SOME_PROGRAM$ on $SOME_FILE$<br>
program_output_line<br>
program_output_line<br>
program_output_line<br>
program_output_line<br>
program_output_line<br>
2016-01-22|{INFO}: Finished running $SOME_PROGRAM$<br>
"""

有谁知道我如何做到这一点?

【问题讨论】:

    标签: python logging sh


    【解决方案1】:

    您可以为Logger 使用的处理程序设置logging.Formatter 对象。它应该实现format(record) 方法,该方法将返回实际显示的字符串。

    import sh
    import logging
    
    class MyFormatter(logging.Formatter):
        def __init__(self, *args, **kwargs):
            logging.Formatter.__init__(self, *args, **kwargs)
            self._enableFormatFlag = True
    
        def enableFormat(self):
            self._enableFormatFlag = True
        def disableFormat(self):
            self._enableFormatFlag = False
    
        def format(self, record):
            if self._enableFormatFlag:
                return logging.Formatter.format(self, record)
            else:
                return record.getMessage()
    
    logger = logging.getLogger('myapp')
    logger.setLevel(logging.INFO)
    handler = logging.StreamHandler()
    logger.addHandler(handler)
    formatter = MyFormatter(fmt="prefix[%(message)s]suffix")
    handler.setFormatter(formatter)
    
    
    def callback(line):
        logger.info(line.strip())
    
    logger.info("Will start program")
    formatter.disableFormat()
    sh.ls(['-l'],_out=callback)
    formatter.enableFormat()
    logger.info("Finished program")
    

    PS:我之前的回答是关于获取回调,抱歉。

    【讨论】:

      【解决方案2】:

      您可以查看 logging.config https://docs.python.org/2/library/logging.config.html

      基本上,您将定义一个专用记录器,该记录器写入与根记录器相同的文件,但使用精简的格式化程序,如format=%(message)s。然后,在 call_back 中,您将显式获取该记录器:logging.getlogger(logger_name)

      【讨论】:

        【解决方案3】:

        您可以通过扩展 logging.Formatter 类来做到这一点。如果日志消息附带可选的元数据 simple=True - 则不会为该特定消息呈现格式

        class ConditionalFormatter(logging.Formatter):
            def format(self, record):
                if hasattr(record, 'simple') and record.simple:
                    return record.getMessage()
                else:
                    return logging.Formatter.format(self, record)
        
        
        rotating_file_formatter = ConditionalFormatter('%(asctime)s %(levelname)s - %(message)s')
        rotating_file.setFormatter(rotating_file_formatter)
        # ...
        
        • 带格式

          logging.info("starting application ...")
          

          日志输出:

          2020-05-01 19:38:05,337 INFO - starting application ...
          
        • 不格式化

          logging.info("starting application ...", extra={'simple': True})
          

          日志输出:

          starting application ...
          

        完整示例

        在此脚本中,我使用控制台日志记录和文件日志记录。在一般日志中,我调用了一个命令 ls -ahl / 并将其所有输出直接传送到日志而不进行格式化:

        #!/usr/bin/env python3
        
        import logging
        import subprocess
        import sys
        from logging.handlers import RotatingFileHandler
        
        
        def initialize_logger(log_file_path):
            rotating_file = RotatingFileHandler(log_file_path, mode='a', maxBytes=5 * 1024 * 1024, backupCount=5, encoding=None, delay=0)
        
            class ConditionalFormatter(logging.Formatter):
                def format(self, record):
                    if hasattr(record, 'simple') and record.simple:
                        return record.getMessage()
                    else:
                        return logging.Formatter.format(self, record)
        
            rotating_file_formatter = ConditionalFormatter('%(asctime)s %(levelname)s - %(message)s')
            rotating_file.setFormatter(rotating_file_formatter)
            rotating_file.setLevel(logging.DEBUG)
        
            console_logger = logging.StreamHandler(sys.stdout)
            console_logger_formatter = logging.Formatter('%(message)s')
            console_logger.setFormatter(console_logger_formatter)
            console_logger.setLevel(logging.INFO)
        
            root_logger = logging.getLogger()
            root_logger.setLevel(logging.DEBUG)
            root_logger.addHandler(rotating_file)
            root_logger.addHandler(console_logger)
        
        
        def main():
            initialize_logger('/var/log/my-app.log')
            logging.info('starting application ...')
        
            command = ["ls", "-ahl"]
            working_directory = '/'
            logging.info(f'running {command} ...')
            process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=working_directory)
        
            with process.stdout:
                for line in iter(process.stdout.readline, b''):
                    line = line.decode('utf-8')
                    line = line.strip()
                    logging.debug(line, extra={'simple': True})
        
            exit_code = process.wait()
            if exit_code == 0:
                logging.debug(f'command "{command}" finished successfully')
            else:
                logging.debug(f'command "{command}" failed with exit code {exit_code}')
        
            logging.info('stopping application')
        
        
        if __name__ == '__main__':
            main()
        

        标准输出:

        starting application ...
        running ['ls', '-ahl'] ...
        stopping application
        

        输出文件/var/log/my-app.log:

        2020-05-01 19:48:06,347 INFO - starting application ...
        2020-05-01 19:48:06,347 INFO - running ['ls', '-ahl', '/'] ...
        total 112K
        drwxr-xr-x  25 root root 4.0K Apr 30 06:55 .
        drwxr-xr-x  25 root root 4.0K Apr 30 06:55 ..
        drwxr-xr-x   2 root root 4.0K Mar 31 06:39 bin
        drwxr-xr-x   3 root root 4.0K May  1 06:02 boot
        drwxrwxr-x   2 root root 4.0K Oct 11  2018 cdrom
        drwxr-xr-x  20 root root 4.2K Apr 30 06:54 dev
        drwxr-xr-x 154 root root  12K Apr 30 06:54 etc
        drwxr-xr-x   3 root root 4.0K Oct 11  2018 home
        lrwxrwxrwx   1 root root   33 Apr 30 06:55 initrd.img -> boot/initrd.img-4.15.0-99-generic
        lrwxrwxrwx   1 root root   33 Apr 30 06:55 initrd.img.old -> boot/initrd.img-4.15.0-96-generic
        drwxr-xr-x  21 root root 4.0K Oct 20  2018 lib
        drwxr-xr-x   2 root root 4.0K Oct 20  2018 lib32
        drwxr-xr-x   2 root root 4.0K Jul 25  2018 lib64
        drwx------   2 root root  16K Oct 11  2018 lost+found
        drwxr-xr-x   4 root root 4.0K Oct 15  2018 media
        drwxr-xr-x   3 root root 4.0K Jun 20  2019 mnt
        drwxrwxrwx  23 root root 4.0K May  1 16:56 opt
        dr-xr-xr-x 302 root root    0 Apr 23 19:57 proc
        drwx------   6 root root 4.0K Apr 29 22:31 root
        drwxr-xr-x  40 root root 1.4K May  1 14:44 run
        drwxr-xr-x   2 root root  12K Feb  9 12:00 sbin
        drwxr-xr-x  15 root root 4.0K Apr 25 11:15 snap
        drwxr-xr-x   2 root root 4.0K Jul 25  2018 srv
        dr-xr-xr-x  13 root root    0 May  1 18:53 sys
        drwxrwxrwt  32 root root 4.0K May  1 19:39 tmp
        drwxr-xr-x  11 root root 4.0K Oct 20  2018 usr
        drwxr-xr-x  15 root root 4.0K Jun 20  2019 var
        lrwxrwxrwx   1 root root   30 Apr 30 06:55 vmlinuz -> boot/vmlinuz-4.15.0-99-generic
        lrwxrwxrwx   1 root root   30 Apr 30 06:55 vmlinuz.old -> boot/vmlinuz-4.15.0-96-generic
        2020-05-01 19:48:06,357 DEBUG - command "['ls', '-ahl', '/']" finished successfully
        2020-05-01 19:48:06,357 INFO - stopping application
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-03-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-07-25
          • 2011-01-04
          • 2016-05-13
          • 1970-01-01
          相关资源
          最近更新 更多