【问题标题】:Suppress newline in Python logging module禁止 Python 日志记录模块中的换行符
【发布时间】:2011-11-02 09:13:57
【问题描述】:

我正在尝试用 Python 的日志记录模块替换临时日志记录系统。我正在使用日志系统在一行上输出长任务的进度信息,因此您可以tail 日志或在控制台中观看它。我已经通过在我的日志记录功能上设置一个标志来抑制该日志消息的换行符并逐个构建行来完成此操作。

所有日志记录都是从单个线程完成的,因此不存在序列化问题。

是否可以使用 Python 的日志记录模块来做到这一点?这是个好主意吗?

【问题讨论】:

  • 如果您想在同一行中记录多个内容,请考虑不要使用logging,而是使用一个好的旧文件对象并直接写入它(并且写入与用于的日志文件不同的文件)其他,基于行的事物)。
  • @ThiefMaster 我现在正在直接写入文件和标准输出。感觉就像我正在重写日志记录,所以如果最终省力,我宁愿使用日志记录。

标签: python logging


【解决方案1】:

Python 3.5.9

class MFileHandler(logging.FileHandler):
  """Handler that controls the writing of the newline character"""

  special_code = '[!n]'

  def emit(self, record) -> None:

    if self.special_code in record.msg:
      record.msg = record.msg.replace( self.special_code, '' )
      self.terminator = ''
    else:
      self.terminator = '\n'

    return super().emit(record)

然后

fHandler = MFileHandler(...)

例子:

# without \n
log.info( 'waiting...[!n]' )
 ...
log.info( 'OK' )

# with \n
log.info( 'waiting...' )
 ...
log.info( 'OK' )

log.txt:

waiting...OK
waiting...
OK

【讨论】:

    【解决方案2】:

    当我遍历一个元组时,我遇到了需要在一行中记录某个部分,但想保留整个记录器。

    首先将输出收集到一个字符串中,然后在我离开该部分后将其发送到记录器。概念示例

    for fld in object._fields: 
      strX = (' {} --> {} ').format(fld, formattingFunction(getattr(obj,fld)))
    debugLine += strX
    logger.debug('{}'.format(debugLine))
    

    【讨论】:

      【解决方案3】:

      如果您想这样做,您可以更改日志处理程序终止符。我正在使用 Python 3.4。正如 Ninjakannon 所述,这是在 Python 3.2 中引入的。

      handler = logging.StreamHandler()
      handler.terminator = ""
      

      当 StreamHandler 写入时,它最后写入终止符。

      【讨论】:

      • 如何将它与记录器集成?
      • 你没有。处理程序是将信息写入文件、套接字、流或其他对象的对象。大多数处理程序都继承自 StreamHandler。终止符变量是一个类级别的变量,因此您可以使用logging.StreamHandler.terminator = "" 为所有处理程序更改它。这应该会更改所有处理程序,但明确设置了终止符的处理程序除外。您还可以遍历记录器处理程序并设置终止符for handler in logger.handlers:...
      【解决方案4】:

      新行 \n 被插入到 StreamHandler 类中。

      如果您真的打算修复这种行为,那么下面是我如何通过 monkey patching emit(self, record) logging.StreamHandler 类中的方法解决此问题的示例。

      猴子补丁是一种在不改变原始源代码的情况下扩展或修改动态语言的运行时代码的方法。这个过程也被称为打鸭子。

      这是emit() 的自定义实现,它省略了换行符:

      def customEmit(self, record):
          # Monkey patch Emit function to avoid new lines between records
          try:
              msg = self.format(record)
              if not hasattr(types, "UnicodeType"): #if no unicode support...
                  self.stream.write(msg)
              else:
                  try:
                      if getattr(self.stream, 'encoding', None) is not None:
                          self.stream.write(msg.encode(self.stream.encoding))
                      else:
                          self.stream.write(msg)
                  except UnicodeError:
                      self.stream.write(msg.encode("UTF-8"))
              self.flush()
          except (KeyboardInterrupt, SystemExit):
              raise
          except:
              self.handleError(record)
      

      然后您将创建一个自定义日志记录类(在这种情况下,从TimedRotatingFileHandler 继承)。

      class SniffLogHandler(TimedRotatingFileHandler):
          def __init__(self, filename, when, interval, backupCount=0,
                       encoding=None, delay=0, utc=0):
      
              # Monkey patch 'emit' method
              setattr(StreamHandler, StreamHandler.emit.__name__, customEmit)
      
              TimedRotatingFileHandler.__init__(self, filename, when, interval,
                                                backupCount, encoding, delay, utc)
      

      有些人可能会争辩说这种类型的解决方案不是 Pythonic 或其他。可能是这样,所以要小心。

      另外,请注意,这将全局修补 SteamHandler.emit(...),因此如果您使用多个日志记录类,那么此补丁也会影响其他日志记录类!

      查看这些以进一步阅读:

      希望对您有所帮助。

      【讨论】:

        【解决方案5】:

        让我们从您的最后一个问题开始:不,我认为这不是一个好主意。 IMO,从长远来看,它会损害日志文件的可读性。

        我建议坚持使用logging 模块并在'tail' 命令上使用'-f' 选项来观察控制台的输出。您可能最终会使用FileHandler。请注意,“延迟”的默认参数是 False,这意味着输出不会被缓冲。

        如果您真的需要禁止换行,我建议您创建自己的处理程序。

        【讨论】:

          猜你喜欢
          • 2020-10-18
          • 2016-05-21
          • 1970-01-01
          • 1970-01-01
          • 2017-06-04
          • 2011-11-29
          • 2021-11-23
          • 1970-01-01
          • 2020-08-11
          相关资源
          最近更新 更多