파이썬 로깅 : 시간 형식으로 밀리 초 사용


163

기본적으로 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) 다음으로 인해 Python 2.6에서 작동하지 않습니다 %f.

logging.Formatter(fmt='%(asctime)s',datefmt='%Y-%m-%d,%H:%M:%S.%f')

1
로케일을 변경하면 도움이 될 수 있습니까?
pajton

1
@ pajton-다음 링크에서 "asctime ()은 로케일 정보를 사용하지 않습니다"라고 표시합니다.- docs.python.org
Jonathan

%f파이썬 2.7.9 또는 3.5.1에서도 작동하지 않습니다.
Antony Hatchkins

4
여기 좋은 대화. logging기본 시간 형식이 ISO 8601을 준수한다고 주장 했기 때문에 여기에 왔습니다 . "T"가 아닌 공백을 사용하여 소수점이 아닌 소수 초 동안 시간과 쉼표를 구분합니다. 그들은 어떻게 그렇게 잘못 될 수 있습니까?
LS

답변:


76

유의하시기 바랍니다 크레이그 맥다니엘의 솔루션은 분명히 낫다.


logging.Formatter의 formatTime메소드는 다음과 같습니다.

def formatTime(self, record, datefmt=None):
    ct = self.converter(record.created)
    if datefmt:
        s = time.strftime(datefmt, ct)
    else:
        t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
        s = "%s,%03d" % (t, record.msecs)
    return s

의 쉼표를 확인하십시오 "%s,%03d". datefmt이유 ct는 a 를 지정하여 해결할 수 없으며 time.struct_time이러한 개체는 밀리 초를 기록하지 않습니다.

정의를 변경하여 객체 대신 객체 ct를 만들려면 (적어도 최신 버전의 Python에서는) 호출 할 수 있으며 마이크로 초 형식을 지정할 수 있습니다 .datetimestruct_timect.strftime%f

import logging
import datetime as dt

class MyFormatter(logging.Formatter):
    converter=dt.datetime.fromtimestamp
    def formatTime(self, record, datefmt=None):
        ct = self.converter(record.created)
        if datefmt:
            s = ct.strftime(datefmt)
        else:
            t = ct.strftime("%Y-%m-%d %H:%M:%S")
            s = "%s,%03d" % (t, record.msecs)
        return s

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

console = logging.StreamHandler()
logger.addHandler(console)

formatter = MyFormatter(fmt='%(asctime)s %(message)s',datefmt='%Y-%m-%d,%H:%M:%S.%f')
console.setFormatter(formatter)

logger.debug('Jackdaws love my big sphinx of quartz.')
# 2011-06-09,07:12:36.553554 Jackdaws love my big sphinx of quartz.

또는 밀리 초를 얻으려면 쉼표를 소수점으로 변경하고 datefmt인수를 생략하십시오 .

class MyFormatter(logging.Formatter):
    converter=dt.datetime.fromtimestamp
    def formatTime(self, record, datefmt=None):
        ct = self.converter(record.created)
        if datefmt:
            s = ct.strftime(datefmt)
        else:
            t = ct.strftime("%Y-%m-%d %H:%M:%S")
            s = "%s.%03d" % (t, record.msecs)
        return s

...
formatter = MyFormatter(fmt='%(asctime)s %(message)s')
...
logger.debug('Jackdaws love my big sphinx of quartz.')
# 2011-06-09 08:14:38.343 Jackdaws love my big sphinx of quartz.

1
그래서 % f는 실제로 밀리 초가 아닌 마이크로 초를 줄 것입니다.
Jonathan

@Jonathan : 죄송 %f합니다. 마이크로 초를 제공합니다. 밀리 초를 얻는 가장 쉬운 방법은 쉼표를 소수점으로 변경하는 것입니다 (위의 편집 참조).
unutbu

3
실제로 STANDARD 형식 옵션을 사용할 수 있기 때문에 이것이 가장 좋은 대답이라고 생각합니다. 나는 실제로 마이크로 초를 원했고 이것이 할 수있는 유일한 옵션이었습니다!
trumpetlicks

감사. 이 답변은 마이크로 초를 얻는 쉬운 솔루션을 제공합니다.
Yongwei Wu

337

이것도 작동해야합니다.

logging.Formatter(fmt='%(asctime)s.%(msecs)03d',datefmt='%Y-%m-%d,%H:%M:%S')

12
감사합니다 : 다음 문서를 참조하십시오. docs.python.org/2/library/logging.html#logrecord-attributes docs.python.org/3/library/logging.html#logrecord-attributes .. 방법이 있습니까? 여전히 시간대 (% z)를 포함합니까? ... 파이썬 로그 (,->)의 ISO8601 형식 시간은 좋을 것입니다.
웨스 터너

19
당신이있는 경우에 때문에이 솔루션은, 장애인한다 %z또는 %Z당신에 datefmt해당하지 이전과 밀리 초 후에 표시 할.
wim

1
그리고 당신이 가지고있는 12 시간 시계를 사용하는 경우 AM또는PM
DollarAkshay

1
: 여기에 내가 무슨 짓을했는지입니다 (... 더 이상 편집 할 수 없습니다) 내 이전 의견에 대한 후속으로 @wim from time import gmtime- # Use UTC rather than local date/time- logging.Formatter.converter = gmtime-logging.basicConfig(datefmt='%Y-%m-%dT%H:%M:%S', format='%(name)s | %(asctime)s.%(msecs)03dZ | %(message)s', level=log_level)
마크

1
@Mark default_msec_format시간과 밀리 초 만 대체되기 때문에 (파이썬 3.7부터)에 시간대를 포함시킬 수 없습니다 . logging출처 :self.default_msec_format % (t, record.msecs)
M. Dudley

27

msecs를 추가하는 것이 더 좋은 방법입니다. 감사합니다. 블렌더에서 Python 3.5.3을 사용하여 수정 한 내용은 다음과 같습니다.

import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s.%(msecs)03d %(levelname)s:\t%(message)s', datefmt='%Y-%m-%d %H:%M:%S')
log = logging.getLogger(__name__)
log.info("Logging Info")
log.debug("Logging Debug")

1
지금까지 가장 간단하고 깨끗한 옵션입니다. logging.info (msg) 등을 호출 할 수 있는데 왜 로거를 얻는 지 확실하지 않지만 형식은 내가 찾던 것입니다. 사용 가능한 모든 속성을 찾는 다른 사용자는 여기를 참조하십시오. docs.python.org/3.6/library/logging.html#logrecord-attributes
naphier

흠 흥미로운 점, 의견 주셔서 감사합니다 그것은 확실히 생각하는 음식입니다. 나중에 방금 진행중인 과정에 대한 교훈으로 추가하고 거기에 있는지 확인하고 여러 가지를 요청했기 때문에 가져 오기 위해 부모 ( '.'를 통해)에 여러 번 호출 할 필요가 없습니다. .info 또는 .debug를 다시 호출하면 참조 조회주기를 저장하는 것이 좋습니다. [let info = logging.info]
마스터 제임스

Jason에게 감사합니다. 때때로 세상을 보는 더 간단한 방법이 있습니다. 어떤 상황이든 아니든 많은 사람들에게 그 진실을 발견하려고 노력하는 것을 두려워하지 마십시오.
마스터 제임스

15

내가 찾은 가장 간단한 방법은 default_msec_format을 재정의하는 것입니다.

formatter = logging.Formatter('%(asctime)s')
formatter.default_msec_format = '%s.%03d'

1
재미 있네요 그러나 이것은 Python 2.7에서 작동하지 않았습니다. x의 일부 값에 대해서는 Python 3.x에서만 작동 할 수 있습니다.
nealmcb

1
@nealmcb 이것은 문서
Mark

3

인스턴스화 후 Formatter보통 설정 formatter.converter = gmtime합니다. 따라서이 경우 @unutbu의 답변이 작동하려면 다음이 필요합니다.

class MyFormatter(logging.Formatter):
    def formatTime(self, record, datefmt=None):
        ct = self.converter(record.created)
        if datefmt:
            s = time.strftime(datefmt, ct)
        else:
            t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
            s = "%s.%03d" % (t, record.msecs)
        return s

2

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

1

화살표 를 사용 하거나 화살표 를 사용 하지 않는 경우. python의 시간 형식을 화살표 대신 사용할 수 있습니다.

import logging

from arrow.arrow import Arrow


class ArrowTimeFormatter(logging.Formatter):

    def formatTime(self, record, datefmt=None):
        arrow_time = Arrow.fromtimestamp(record.created)

        if datefmt:
            arrow_time = arrow_time.format(datefmt)

        return str(arrow_time)


logger = logging.getLogger(__name__)

default_handler = logging.StreamHandler()
default_handler.setFormatter(ArrowTimeFormatter(
    fmt='%(asctime)s',
    datefmt='YYYY-MM-DD HH:mm:ss.SSS'
))

logger.setLevel(logging.DEBUG)
logger.addHandler(default_handler)

이제 속성 에서 모든 화살표의 시간 형식 을 사용할 수 있습니다 datefmt.


-1

tl; dr ISO 형식의 날짜를 찾는 사람들의 경우 :

datefmt : '% Y- % m- % d % H : % M : % S. % 03d % z'


-3

현재 다음은 python 3과 완벽하게 작동합니다.

         logging.basicConfig(level=logging.DEBUG,
                     format='%(asctime)s %(levelname)-8s %(message)s',
                     datefmt='%Y/%m/%d %H:%M:%S.%03d',
                     filename=self.log_filepath,
                     filemode='w')

다음과 같은 출력을 제공합니다

2020/01/11 18 : 51 : 19.011 정보


1
작동하지 않습니다. % d 님이 날짜를 인쇄 중입니다. 귀하의 예에서 날짜 앞에 0이 채워져 인쇄됩니다.
Klik
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.