Python 日志记录:使用毫秒时间格式
默认情况下 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)
但是 文档没有指定如何格式化毫秒。我发现这个所以问题讨论了微秒,但是a)我更喜欢毫秒,b)由于%f
,以下内容在Python 2.6(我正在研究)上不起作用:
logging.Formatter(fmt='%(asctime)s',datefmt='%Y-%m-%d,%H:%M:%S.%f')
By default logging.Formatter('%(asctime)s')
prints with the following format:
2011-06-09 10:54:40,638
where 638 is the millisecond. I need to change the comma to a dot:
2011-06-09 10:54:40.638
To format the time I can use:
logging.Formatter(fmt='%(asctime)s',datestr=date_format_str)
however the documentation doesn't specify how to format milliseconds. I've found this SO question which talks about microseconds, but a) I would prefer milliseconds and b) the following doesn't work on Python 2.6 (which I'm working on) due to the %f
:
logging.Formatter(fmt='%(asctime)s',datefmt='%Y-%m-%d,%H:%M:%S.%f')
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(18)
这也应该有效:
This should work too:
请注意 Craig McDaniel 的解决方案是更好的选择,除非您需要支持所有 ISO 8601 格式代码。
logging.Formatter 的
formatTime
方法如下所示:注意
"%s,%03d"
中的逗号。这无法通过指定datefmt
来解决,因为ct
是time.struct_time
并且这些对象不记录毫秒。如果我们更改
ct
的定义,使其成为datetime
对象而不是struct_time
,那么(至少对于现代版本的 Python)我们可以调用ct.strftime
,然后我们可以使用%f
来格式化微秒:或者,要获取毫秒,将逗号更改为小数点,并省略
datefmt
参数:Please note Craig McDaniel's solution is preferable, unless you need support for all ISO 8601 format codes.
logging.Formatter's
formatTime
method looks like this:Notice the comma in
"%s,%03d"
. This can not be fixed by specifying adatefmt
becausect
is atime.struct_time
and these objects do not record milliseconds.If we change the definition of
ct
to make it adatetime
object instead of astruct_time
, then (at least with modern versions of Python) we can callct.strftime
and then we can use%f
to format microseconds:Or, to get milliseconds, change the comma to a decimal point, and omit the
datefmt
argument:添加毫秒是更好的选择,谢谢。
这是我在 Blender 中使用 Python 3.5.3 进行的修改
Adding msecs was the better option, Thanks.
Here is my amendment using this with Python 3.5.3 in Blender
我发现的最简单的方法是覆盖default_msec_format:
The simplest way I found was to override default_msec_format:
我想出了一个双行代码,让 Python 日志记录模块以 RFC 3339(符合 ISO 1801 标准)格式输出时间戳,并具有格式正确的毫秒和时区和,而无需外部依赖项:
示例:
或者,最后一行可以写成如下:
该方法也可以用于特定的格式化程序实例,而不是在类级别覆盖,在这种情况下,您需要从方法签名中删除
self
。I figured out a two-liner to get the Python logging module to output timestamps in RFC 3339 (ISO 1801 compliant) format, with both properly formatted milliseconds and timezone and without external dependencies:
Example:
Alternatively, that last line could be written out as follows:
That method could also be used on specific formatter instances, rather than overriding at the class level, in which case you will need to remove
self
from the method signature.这里有许多过时的、过于复杂的和奇怪的答案。原因是文档不充分,简单的解决方案是仅使用
basicConfig()
并按如下方式设置:这里的技巧是您还必须设置
datefmt
参数,因为默认把它弄乱了,并且不是(当前)显示在Python 操作方法文档。因此,请查看此处。另一种可能更简洁的方法是用以下方法覆盖
default_msec_format
变量:但是,由于未知原因,该方法不起作用。
<子>PS。我正在使用 Python 3.8。
Many outdated, over-complicated and weird answers here. The reason is that the documentation is inadequate and the simple solution is to just use
basicConfig()
and set it as follows:The trick here was that you have to also set the
datefmt
argument, as the default messes it up and is not what is (currently) shown in the how-to python docs. So rather look here.An alternative and possibly cleaner way, would have been to override the
default_msec_format
variable with:However, that did not work for unknown reasons.
PS. I am using Python 3.8.
TLDR:虽然这不是OP所要求的,但如果您想将所有日志时间戳打印为带有毫秒和UTC偏移量的ISO8601,您可以覆盖默认格式化程序
formatTime
,如下所示:产生这样的日志
%(asctime)s
通过logging.Formatter.formatTime(self, record)
,文档指出formatTime
将使用time.strftime()
与datetime.strftime()
。time.strftime
无法打印毫秒,而datetime.strftime()
另一方面有%f
。因此您不能在datefmt
上使用%f
。如果您只需将
,
(逗号)更改为.
(点),您就可以使用其他答案中结合%(asctime) 的简单选项s
和%(msecs)03d
像这样(使用logging.config.dictConfig()
和 YAML 文件)但是 如果您需要的话,将无法工作例如,在毫秒后添加 UTC 偏移量/时区。
为了获得更合理的时间戳格式,您可以实现自己的格式化程序,该格式化程序是
logging.Formatter
的子类,并且只需覆盖formatTime
即可。例如,以下格式化程序将使用datetime.isoformat()
:在上面的代码中,
record.created
是LogRecord
属性 表示秒数 ( float) 自time.time()
datetime.fromtimestamp()
是将纪元秒转换为日期时间的类方法(简单).astimezone()
将原始日期时间转换为 时区感知 本地时区的日期时间isoformat()
:转换时区感知日期时间转换为 ISO8601 字符串。上述配置结果为:
其中
%(asctime)s
值来自CustomFormatter.formatTime()
最终您可以替换
logging.Formatter.formatTime
> 使用您自己的实现而不是创建新的格式化程序:TLDR: Although it's not what the OP asked for, if you want to print all log timestamps as ISO8601 with milliseconds and UTC offset you can overwrite the default formatter
formatTime
like this:produces logs like this
The
%(asctime)s
is formatted throughlogging.Formatter.formatTime(self, record)
, the documentation states thatformatTime
will usetime.strftime()
which is not the same asdatetime.strftime()
.time.strftime
has no way of printing milliseconds ,datetime.strftime()
on the other hand has%f
. So you can't use%f
on thedatefmt
.If you only need to change the
,
(comma) to a.
(dot) you have the simple options from other answers combining%(asctime)s
, and%(msecs)03d
like so (usinglogging.config.dictConfig()
and a YAML file)But that will not work if you need to add the UTC offset /timezone after the milliseconds, for example.
In order to have a more sensible timestamp formatting you can implement your own formatter that subclasses
logging.Formatter
and just overrideformatTime
. For example, the following formatter will produce logs with timestamps in ISO8601 including milliseconds and UTC offset by usingdatetime.isoformat()
:In the code above
record.created
is theLogRecord
attribute representing the number of seconds (float) since the epoch returned bytime.time()
datetime.fromtimestamp()
is a class method that converts the epoch seconds to a datetime (naive).astimezone()
converts the naive datetime to timezone-aware datetime in the local timezoneisoformat()
: converts the timezone aware datetime to a ISO8601 string.The above configuration results in :
where
%(asctime)s
value comes fromCustomFormatter.formatTime()
Ultimately you can replace the
logging.Formatter.formatTime
with your own implementation instead of creating a new formatter:不需要
datetime
模块并且不像其他解决方案那样受到限制的简单扩展是使用简单的字符串替换,如下所示:这样可以根据需要编写日期格式,甚至允许对于区域差异,使用
%F
表示毫秒。例如:A simple expansion that doesn't require the
datetime
module and isn't handicapped like some other solutions is to use simple string replacement like so:This way a date format can be written however you want, even allowing for region differences, by using
%F
for milliseconds. For example:实例化
Formatter
后,我通常设置formatter.converter = gmtime
。因此,为了让 @unutbu 的答案在这种情况下起作用,您需要:After instantiating a
Formatter
I usually setformatter.converter = gmtime
. So in order for @unutbu's answer to work in this case you'll need:我所需要做的就是在创建格式化程序之前设置
default_msec_format
属性。All I needed to do was set
default_msec_format
attribute before creating the formatter.如果您使用 箭头 或者您不介意使用箭头。您可以用 python 的时间格式替换 arrow 的时间格式。
现在,您可以在
datefmt
arrow 的时间格式 > 属性。If you are using arrow or if you don't mind using arrow. You can substitute python's time formatting for arrow's one.
Now you can use all of arrow's time formatting in
datefmt
attribute.如果您更喜欢使用
style='{'
,fmt="{asctime}.{msecs:0<3.0f}"
会将您的微秒用 0 填充到三位为了一致性。If you prefer to use
style='{'
,fmt="{asctime}.{msecs:0<3.0f}"
will 0-pad your microseconds to three places for consistency.在花费了我一些宝贵的时间之后,下面的技巧对我有用。我刚刚在
settings.py
中更新了我的格式化程序,并将datefmt
添加为%y/%b/%Y %H:%M:%S
并将毫秒附加到 asctime,如下所示{asctime}.{msecs:0<3.0f}
EG:
After burning some of my precious time the below hack worked for me. I just updated my formatter in
settings.py
and addeddatefmt
as%y/%b/%Y %H:%M:%S
and appended the milliseconds to the asctime like this{asctime}.{msecs:0<3.0f}
E.G:
使用这个智能答案来获取时区和选择的答案,您可以使用您的构造毫秒和时区所需的格式:
就我个人而言,我喜欢以 UTC 格式保存所有日志,但也会在日志中明确显示此格式,因为没有时区的日期时间在多区域应用程序中毫无意义:
Using this smart answer for the timezone and the chosen answer, you can construct the millisecond and timezone with your desired format:
Personally, I like to keep all the logs in UTC but also have this explicitly in the log as a datetime without a timezone is meaningless in a multizone application:
我对此的看法如下:
上面添加了对日期格式“%f”的支持,因此可以像往常一样继续使用日志记录模块,例如:
My take on this is the following:
The above adds support for "%f" in the date format, and so one can continue using the logging module as usual, for example:
要允许用户指定包含
%f
的datefmt
,您可以创建自定义格式化程序并重写formatTime()
方法。由于重写使用
super()
来获取默认格式化时间,因此此代码不会更改formatTime()
方法的默认行为。请注意,代码会将
%f
截断为毫秒,而不是微秒。下面的代码执行以下操作 -
super()
来获取格式化时间。record.msecs
作为基础,创建要在格式化时间中使用的毫秒 (msecs
)。%f
作为分隔符分割格式化时间。msecs
上的分割格式化时间。To allow users to specify a
datefmt
that contains%f
, you could create a custom Formatter and override theformatTime()
method.Because the override is using
super()
to get the default formatted time, this code doesn't change the default behaviour of theformatTime()
method.Note that the code will truncate
%f
to milliseconds, as opposed to microseconds.The code below does the following -
super()
to get the formatted time.msecs
) to use in the formatted time, usingrecord.msecs
as the base.%f
as the separator.msecs
.tl;dr 对于在这里寻找 ISO 格式日期的人来说:
不要使用类似 '%Y-%m-%d %H:%M:%S.%03d%z' 的东西,而是创建你自己的类,如 @unutbu 所示。这是 iso 日期格式:
tl;dr for folks looking here for an ISO formatted date:
instead of using something like '%Y-%m-%d %H:%M:%S.%03d%z', create your own class as @unutbu indicated. Here's one for iso date format:
到目前为止,以下内容与 python 3 完美配合。
给出以下输出
As of now the following works perfectly with python 3 .
gives the following output