如何在python日志中插入换行符?

时间:2013-11-21 03:16:04

标签: python logging newline

import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
logging.info('hello')
logging.warning('\n new hello')
  

11:15:01 INFO你好   11:16:49警告
  新你好

由于日志拥挤,我想在 asctimelevelname之前明确插入换行符。这可能不修改format吗?

我查看logging模块并搜索了一下,找不到可行的方法。

12 个答案:

答案 0 :(得分:26)

我有两个解决方案,第一个很容易,但输出不是很干净。第二种方法将产生您想要的确切输出,但它更复杂一些。

方法1

要生成一个空行,只需使用新行记录一个空字符串:

import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
logging.info('hello')
logging.info('\n')
logging.warning('new hello')

输出将有一个空的信息行,这不是很干净:

  

16:07:26 INFO你好   16:07:26 INFO

     

16:07:26警告新招呼

方法2

在这种方法中,我创建了两个不同的处理程序。我大部分时间都在使用的console_handler。当我需要一个新行时,我切换到第二个处理程序blank_handler

import logging
import types

def log_newline(self, how_many_lines=1):
    # Switch handler, output a blank line
    self.removeHandler(self.console_handler)
    self.addHandler(self.blank_handler)
    for i in range(how_many_lines):
        self.info('')

    # Switch back
    self.removeHandler(self.blank_handler)
    self.addHandler(self.console_handler)

def create_logger():
    # Create a handler
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.DEBUG)
    console_handler.setFormatter(logging.Formatter(fmt="%(name)s %(levelname)-8s: %(message)s"))

    # Create a "blank line" handler
    blank_handler = logging.StreamHandler()
    blank_handler.setLevel(logging.DEBUG)
    blank_handler.setFormatter(logging.Formatter(fmt=''))

    # Create a logger, with the previously-defined handler
    logger = logging.getLogger('logging_test')
    logger.setLevel(logging.DEBUG)
    logger.addHandler(console_handler)

    # Save some data and add a method to logger object
    logger.console_handler = console_handler
    logger.blank_handler = blank_handler
    logger.newline = types.MethodType(log_newline, logger)

    return logger

if __name__ == '__main__':
    logger = create_logger()
    logger.info('Start reading database')
    logger.info('Updating records ...')
    logger.newline()
    logger.info('Finish updating records')

输出是您想要看到的:

logging_test INFO    : Start reading database
logging_test INFO    : Updating records ...

logging_test INFO    : Finish updating records

讨论

  • 如果你能忍受不太完美的输出,方法1就是你要走的路。它具有简单,省力的优点。
  • 第二种方法正确地完成了工作,但它有点牵扯。它创建了两个不同的处理程序并切换它们以实现您的目标。
  • 使用方法2的另一个缺点是,您必须通过搜索logging并将其替换为logger来更改代码。您必须注意仅替换相关部分,并留下logging.DEBUG这样的文本。

答案 1 :(得分:5)

你能不能在第一次问候后添加换行符?即。

logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
logging.info('hello\n')
logging.info('new hello')

将输出

2014-08-06 11:37:24,061 INFO    : hello

2014-08-06 11:37:24,061 INFO    : new hello

答案 2 :(得分:3)

使用在不同时间使用不同格式字符串的自定义Formatter。您无法使用basicConfig()执行此操作 - 您必须使用logging API的其他部分。

class MyFormatter(logging.Formatter):
    def format(self, record):
        # set self._fmt to value with or without newline,
        # as per your decision criteria
        # self._fmt = ...
        return super(MyFormatter, self).format(record)

或者,您可以调用super方法,然后在返回之前修改字符串以插入换行符(如果它取决于行长度,比如说)。

答案 3 :(得分:1)

插入我想出的换行符的最简单方法:

logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s\n\r%(message)s', datefmt='%H:%M:%S')
logging.info('hello')
logging.info('new hello')
  

11:50:32 INFO
  你好
  11:50:32 INFO
  新你好

答案 4 :(得分:1)

作为Hai Vu 方法2 的替代方案,您每次要记录新行时都可以重置处理程序Formatter

import logging
import types

def log_newline(self, how_many_lines=1):
    # Switch formatter, output a blank line
    self.handler.setFormatter(self.blank_formatter)

    for i in range(how_many_lines):
        self.info('')

    # Switch back
    self.handler.setFormatter(self.formatter)


def create_logger():
    # Create a handler
    handler = logging.StreamHandler()
    handler.setLevel(logging.DEBUG)
    formatter = logging.Formatter(fmt="%(name)s %(levelname)-8s: %(message)s")        
    blank_formatter = logging.Formatter(fmt="")
    handler.setFormatter(formatter)


    # Create a logger, with the previously-defined handler
    logger = logging.getLogger('logging_test')
    logger.setLevel(logging.DEBUG)
    logger.addHandler(handler)

    # Save some data and add a method to logger object
    logger.handler = handler
    logger.formatter = formatter
    logger.blank_formatter = blank_formatter
    logger.newline = types.MethodType(log_newline, logger)

    return logger

if __name__ == '__main__':
    logger = create_logger()
    logger.info('Start reading database')
    logger.info('Updating records ...')
    logger.newline()
    logger.info('Finish updating records')

输出

logging_test INFO    : Start reading database  
logging_test INFO    : Updating records ...

logging_test INFO    : Finish updating records

这样做的好处是你有一个处理程序。例如,如果您想在程序的每次新运行中清理日志文件,则可以定义要编写的FileHandler mode - 属性。

答案 5 :(得分:1)

如果您只是想在开发中输出一些调试代码,那么您可能不想在此花费时间。 5秒的修复是这样;

str = "\n\n\n"
log.getLogger().debug(str)

记录器是标准的python记录器

答案 6 :(得分:1)

如果使用的是Python 3,最简单的解决方案是使用f字符串:

logging.info( f'hello\n' )

答案 7 :(得分:1)

在没有日志记录服务的情况下写日志文件怎么办?

fn_log = 'test.log'
logging.basicConfig(filename=fn_log, level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
logging.info('hello')
logging.warning('no empty line')

def empty_line(fn_log):
    new_empty_line = open(fn_log,'a+')
    new_empty_line.write('\n')
    new_empty_line.close()

empty_line(fn_log)
logging.warning('hello') 

输出:

09:26:00 INFO hello
11:51:05 INFO hello
11:51:05 WARNING no empty line

11:51:05 WARNING hello

答案 8 :(得分:0)

像这样的东西。在\nasctime

之间levelname添加>>> logging.basicConfig(level=logging.DEBUG, format='%(asctime)s\n %(levelname)s %(message)s',datefmt='%H:%M:%S')
{{1}}

答案 9 :(得分:0)

跟随Vinay Salip的有用答案(下面),我这样做了(我使用的是python3超类约定,但super(MyFormatter, self)同样有效)...

class MyFormatter(logging.Formatter):
    def format(self, record):
        return super().format(record).replace(r'\n', '\n')

然后,我可以按如下方式嵌入换行符:

logging.info('Message\\n\\n\\n\\nOther stuff')

logging.info(r'Message\n\n\n\nOther stuff')

答案 10 :(得分:0)

如果使用FileHandler或其后代,这两个功能可能会有所帮助。另一个好处是,附加到记录器的所有FileHandler类型处理程序都应获取换行符。

def getAllLoggerFilenames(logger):
  """ Returns array of all log filenames attached to the logger. """
  logFiles = [];
  parent = logger.__dict__['parent'];
  if parent.__class__.__name__ == 'RootLogger':
    for h in logger.__dict__['handlers']:
      if h.baseFilename:
        logFiles.append(h.baseFilename);
  else:
    logFiles = getAllLoggerFilenames(parent);
  return logFiles;

def logBlankLine(logger):
  """ This utility method writes a blank line to the log. """
  logNames = getAllLoggerFilenames(logger)
  for fn in logNames:
    with open(fn, 'a') as fh:
      fh.write("\n")

用法:

# We use YAML for logging config files, YMMV:
with open(logConfig, 'rt') as f:
  logging.config.dictConfig(yaml.safe_load(f.read()))

logger = logging.getLogger("test.test")

logger.info("line 1")
logBlankLine(logger)
logger.info("line 2")

输出:

2019/12/22 16:33:59.152: INFO    : test.test                 : line 1

2019/12/22 16:33:59.152: INFO    : test.test                 : line 2

答案 11 :(得分:-1)

您可以尝试以下解决方案。简单明了。

logging.debug("\b" * 20)  # output blank line using escape character
logging.debug("debug message")