默认情况下logging.Formatter('%(asctime)s')打印如下格式:
2011-06-09 10:54:40,638
638是毫秒。我需要把逗号换成一个点:
2011-06-09 10:54:40.638
格式化我可以使用的时间:
logging.Formatter(fmt='%(asctime)s',datestr=date_format_str)
但是,文档没有指定如何格式化毫秒。我发现了这个SO问题,它谈论的是微秒,但是a)我更喜欢毫秒,b)由于%f,下面的问题在Python 2.6(我正在工作)上不起作用:
logging.Formatter(fmt='%(asctime)s',datefmt='%Y-%m-%d,%H:%M:%S.%f')
一个简单的扩展不需要datetime模块,也不像其他解决方案那样受到限制,它使用简单的字符串替换,如下所示:
import logging
import time
class MyFormatter(logging.Formatter):
def formatTime(self, record, datefmt=None):
ct = self.converter(record.created)
if datefmt:
if "%F" in datefmt:
msec = "%03d" % record.msecs
datefmt = datefmt.replace("%F", msec)
s = time.strftime(datefmt, ct)
else:
t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
s = "%s,%03d" % (t, record.msecs)
return s
通过使用%F表示毫秒,可以任意编写日期格式,甚至允许区域差异。例如:
log = logging.getLogger(__name__)
log.setLevel(logging.INFO)
sh = logging.StreamHandler()
log.addHandler(sh)
fm = MyFormatter(fmt='%(asctime)s-%(levelname)s-%(message)s',datefmt='%H:%M:%S.%F')
sh.setFormatter(fm)
log.info("Foo, Bar, Baz")
# 03:26:33.757-INFO-Foo, Bar, Baz
这里有许多过时的、过于复杂和奇怪的答案。原因是文档是不充分的,简单的解决方案是使用basicConfig(),并设置如下:
logging.basicConfig(datefmt='%Y-%m-%d %H:%M:%S', format='{asctime}.{msecs:0<3.0f} {name} {threadName} {levelname}: {message}', style='{')
这里的技巧是,你还必须设置datefmt参数,因为默认的参数会把它弄乱,并且不是(目前)在python指南文档中显示的内容。所以还是看这里吧。
另一种可能更干净的方法是覆盖default_msec_format变量:
formatter = logging.Formatter('%(asctime)s')
formatter.default_msec_format = '%s.%03d'
然而,由于未知的原因,这并没有起作用。
PS.我使用的是Python 3.8。
我想出了一个双行程序,让Python日志模块输出RFC 3339 (ISO 1801兼容)格式的时间戳,有正确格式化的毫秒和时区,并且没有外部依赖:
import datetime
import logging
# Output timestamp, as the default format string does not include it
logging.basicConfig(format="%(asctime)s: level=%(levelname)s module=%(module)s msg=%(message)s")
# Produce RFC 3339 timestamps
logging.Formatter.formatTime = (lambda self, record, datefmt=None: datetime.datetime.fromtimestamp(record.created, datetime.timezone.utc).astimezone().isoformat())
例子:
>>> logging.getLogger().error("Hello, world!")
2021-06-03T13:20:49.417084+02:00: level=ERROR module=<stdin> msg=Hello, world!
或者,最后一行可以写成这样:
def formatTime_RFC3339(self, record, datefmt=None):
return (
datetime.datetime.fromtimestamp(record.created, datetime.timezone.utc)
.astimezone()
.isoformat()
)
logging.Formatter.formatTime = formatTime_RFC3339
该方法也可以用于特定的格式化程序实例,而不是在类级别上重写,在这种情况下,您将需要从方法签名中删除self。