bed*_*wyr 63 python logging string-formatting
我正在使用Python的logging
机制将输出打印到屏幕上.我可以使用print语句执行此操作,但我希望允许用户更精细地调整粒度以禁用某些类型的输出.我喜欢为错误打印的格式,但是当输出级别为"info"时,我更喜欢更简单的格式.
例如:
logger.error("Running cmd failed")
logger.info("Running cmd passed")
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我希望以不同的方式打印错误的格式:
Run Code Online (Sandbox Code Playgroud)# error Aug 27, 2009 - ERROR: Running cmd failed # info Running cmd passed
是否可以为不同的日志级别设置不同的格式而无需多个日志记录对象?我宁愿在没有修改记录器的情况下这样做,因为有大量的if/else语句来确定如何记录输出.
JS.*_*JS. 65
我刚遇到这个问题并且无法填写上面例子中留下的"漏洞".这是我使用的更完整,有效的版本.希望这有助于某人:
# Custom formatter
class MyFormatter(logging.Formatter):
err_fmt = "ERROR: %(msg)s"
dbg_fmt = "DBG: %(module)s: %(lineno)d: %(msg)s"
info_fmt = "%(msg)s"
def __init__(self, fmt="%(levelno)s: %(msg)s"):
logging.Formatter.__init__(self, fmt)
def format(self, record):
# Save the original format configured by the user
# when the logger formatter was instantiated
format_orig = self._fmt
# Replace the original format with one customized by logging level
if record.levelno == logging.DEBUG:
self._fmt = MyFormatter.dbg_fmt
elif record.levelno == logging.INFO:
self._fmt = MyFormatter.info_fmt
elif record.levelno == logging.ERROR:
self._fmt = MyFormatter.err_fmt
# Call the original formatter class to do the grunt work
result = logging.Formatter.format(self, record)
# Restore the original format configured by the user
self._fmt = format_orig
return result
Run Code Online (Sandbox Code Playgroud)
编辑:
Halloleo的致意,以下是如何在脚本中使用上述内容的示例:
fmt = MyFormatter()
hdlr = logging.StreamHandler(sys.stdout)
hdlr.setFormatter(fmt)
logging.root.addHandler(hdlr)
logging.root.setLevel(DEBUG)
Run Code Online (Sandbox Code Playgroud)
编辑2:
Python3的日志记录有所改变.请参阅此处获取Python3方法.
Vin*_*jip 32
是的,您可以通过自定义Formatter
类来完成此操作:
class MyFormatter(logging.Formatter):
def format(self, record):
#compute s according to record.levelno
#for example, by setting self._fmt
#according to the levelno, then calling
#the superclass to do the actual formatting
return s
Run Code Online (Sandbox Code Playgroud)
然后将一个MyFormatter
实例附加到您的处理程序.
est*_*ani 16
再次像JS回答,但更紧凑.
class SpecialFormatter(logging.Formatter):
FORMATS = {logging.DEBUG :"DBG: %(module)s: %(lineno)d: %(message)s",
logging.ERROR : "ERROR: %(message)s",
logging.INFO : "%(message)s",
'DEFAULT' : "%(levelname)s: %(message)s"}
def format(self, record):
self._fmt = self.FORMATS.get(record.levelno, self.FORMATS['DEFAULT'])
return logging.Formatter.format(self, record)
hdlr = logging.StreamHandler(sys.stderr)
hdlr.setFormatter(SpecialFormatter())
logging.root.addHandler(hdlr)
logging.root.setLevel(logging.INFO)
Run Code Online (Sandbox Code Playgroud)
Ser*_*kov 12
定义一个类
import logging
class CustomFormatter(logging.Formatter):
"""Logging Formatter to add colors and count warning / errors"""
grey = "\x1b[38;21m"
yellow = "\x1b[33;21m"
red = "\x1b[31;21m"
bold_red = "\x1b[31;1m"
reset = "\x1b[0m"
format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)"
FORMATS = {
logging.DEBUG: grey + format + reset,
logging.INFO: grey + format + reset,
logging.WARNING: yellow + format + reset,
logging.ERROR: red + format + reset,
logging.CRITICAL: bold_red + format + reset
}
def format(self, record):
log_fmt = self.FORMATS.get(record.levelno)
formatter = logging.Formatter(log_fmt)
return formatter.format(record)
Run Code Online (Sandbox Code Playgroud)
实例化记录器
# create logger with 'spam_application'
logger = logging.getLogger("My_app")
logger.setLevel(logging.DEBUG)
# create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(CustomFormatter())
logger.addHandler(ch)
Run Code Online (Sandbox Code Playgroud)
并使用!
logger.debug("debug message")
logger.info("info message")
logger.warning("warning message")
logger.error("error message")
logger.critical("critical message")
Run Code Online (Sandbox Code Playgroud)
您还可以创建一个Formatter,根据record.levelno(或其他条件)委托给其他格式化程序,而不是依赖于样式或内部字段.在我看来,这是一个稍微清洁的解决方案.下面的代码适用于任何python版本> = 2.7:
简单的方法看起来像这样:
class MyFormatter(logging.Formatter):
default_fmt = logging.Formatter('%(levelname)s in %(name)s: %(message)s')
info_fmt = logging.Formatter('%(message)s')
def format(self, record):
if record.levelno == logging.INFO:
return self.info_fmt.format(record)
else:
return self.default_fmt.format(record)
Run Code Online (Sandbox Code Playgroud)
但你可以使它更通用:
class VarFormatter(logging.Formatter):
default_formatter = logging.Formatter('%(levelname)s in %(name)s: %(message)s')
def __init__(self, formats):
""" formats is a dict { loglevel : logformat } """
self.formatters = {}
for loglevel in formats:
self.formatters[loglevel] = logging.Formatter(formats[loglevel])
def format(self, record):
formatter = self.formatters.get(record.levelno, self.default_formatter)
return formatter.format(record)
Run Code Online (Sandbox Code Playgroud)
我在这里使用了一个dict作为输入,但显然你也可以使用元组,**kwargs,无论你的船是什么漂浮.然后将使用如下:
formatter = VarFormatter({logging.INFO: '[%(message)s]',
logging.WARNING: 'warning: %(message)s'})
<... attach formatter to logger ...>
Run Code Online (Sandbox Code Playgroud)
这是对estani对新实现的回答的改编logging.Formatter
,现在它依赖于格式化风格.我的'{'
风格依赖于风格格式,但它可以适应.可以改进为更一般,并允许选择格式样式和自定义消息作为参数__init__
.
class SpecialFormatter(logging.Formatter):
FORMATS = {logging.DEBUG : logging._STYLES['{']("{module} DEBUG: {lineno}: {message}"),
logging.ERROR : logging._STYLES['{']("{module} ERROR: {message}"),
logging.INFO : logging._STYLES['{']("{module}: {message}"),
'DEFAULT' : logging._STYLES['{']("{module}: {message}")}
def format(self, record):
# Ugly. Should be better
self._style = self.FORMATS.get(record.levelno, self.FORMATS['DEFAULT'])
return logging.Formatter.format(self, record)
hdlr = logging.StreamHandler(sys.stderr)
hdlr.setFormatter(SpecialFormatter())
logging.root.addHandler(hdlr)
logging.root.setLevel(logging.INFO)
Run Code Online (Sandbox Code Playgroud)
以上解决方案适用于3.3.3版本。但是,使用3.3.4时,会出现以下错误。
FORMATS = { logging.DEBUG : logging._STYLES['{']("{module} DEBUG: {lineno}: {message}"),
Run Code Online (Sandbox Code Playgroud)
TypeError:“元组”对象不可调用
在日志记录类Lib \ logging__init __。py中进行搜索后,我发现数据结构已从3.3.3更改为3.3.4,这导致了问题
_STYLES = {
'%': PercentStyle,
'{': StrFormatStyle,
'$': StringTemplateStyle
}
Run Code Online (Sandbox Code Playgroud)
_STYLES = {
'%': (PercentStyle, BASIC_FORMAT),
'{': (StrFormatStyle, '{levelname}:{name}:{message} AA'),
'$': (StringTemplateStyle, '${levelname}:${name}:${message} BB'),
}
Run Code Online (Sandbox Code Playgroud)
因此,更新的解决方案是
class SpecialFormatter(logging.Formatter):
FORMATS = {logging.DEBUG : logging._STYLES['{'][0]("{module} DEBUG: {lineno}: {message}"),
logging.ERROR : logging._STYLES['{'][0]("{module} ERROR: {message}"),
logging.INFO : logging._STYLES['{'][0]("{module}: {message}"),
'DEFAULT' : logging._STYLES['{'][0]("{module}: {message}")}
def format(self, record):
# Ugly. Should be better
self._style = self.FORMATS.get(record.levelno, self.FORMATS['DEFAULT'])
return logging.Formatter.format(self, record)
Run Code Online (Sandbox Code Playgroud)
如果您只是想跳过某些级别的格式化,您可以做一些比其他答案更简单的事情,如下所示:
class FormatterNotFormattingInfo(logging.Formatter):
def __init__(self, fmt = '%(levelname)s:%(message)s'):
logging.Formatter.__init__(self, fmt)
def format(self, record):
if record.levelno == logging.INFO:
return record.getMessage()
return logging.Formatter.format(self, record)
Run Code Online (Sandbox Code Playgroud)
通过不使用 self._fmt 或 self._style 等内部变量,这也具有在 3.2 版本之前和之后工作的优点。
归档时间: |
|
查看次数: |
16365 次 |
最近记录: |