2011-06-09 12 views
96

Domyślnie logging.Formatter('%(asctime)s') drukuje z następującym formacie:Python rejestrowania: Użycie milisekund w formacie czasowym

2011-06-09 10:54:40,638 

gdzie jest 638 milisekund. Muszę zmienić przecinek kropką:

2011-06-09 10:54:40.638 

Aby sformatować czasu mogę użyć:

logging.Formatter(fmt='%(asctime)s',datestr=date_format_str) 

jednak documentation nie precyzuje sposobu formatowania milisekund. Znalazłem this SO question który mówi o mikrosekund, ale a) Wolałbym milisekund oraz b) dodaje nie działa w Pythonie 2.6 (który ja pracuję) ze względu na %f:

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

Może zmiana ustawienia może pomóc? – pajton

+1

@ pajton - w poniższym linku jest napisane: "Informacje o lokalizacji nie są używane przez asctime()" - http://docs.python.org/library/time.html#time.asctime – Jonathan

+0

'% f' nie działa na pytonie 2.7.9 lub 3.5.1 albo –

Odpowiedz

44

Uwaga: Craig McDaniel's solution jest wyraźnie lepszy.


logging.Formatter za formatTime metoda wygląda następująco:

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 

Wskazówka przecinek w "%s,%03d". Nie można tego naprawić, określając wartość datefmt, ponieważ obiekty te nie rejestrują milisekund.

Jeśli zmienimy definicję ct aby to datetime obiekt zamiast struct_time, to (przynajmniej w nowoczesnych wersjach Pythona) możemy nazwać ct.strftime i wtedy możemy użyć %f do formatu mikrosekund:

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. 

lub, aby uzyskać milisekund zmienić przecinek kropką dziesiętną, a pominąć datefmt argument:

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. 
+0

, więc% f faktycznie dałby mikrosekundy, a nie milisekundy, prawda? – Jonathan

+0

@ Jonathan: Oops, masz rację, '% f' daje mikrosekundy. Przypuszczam, że najłatwiejszym sposobem uzyskania milisekund jest zmiana przecinka na separator dziesiętny (patrz edycja powyżej). – unutbu

+2

Chciałbym dać Ci jeszcze raz, gdybym mógł, dziękuję za aktualizację :) – Jonathan

211

To powinno działać zbyt:

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

Dzięki: Oto dokumenty dla tych: https://docs.python.org/2/library/logging.html#logrecord-attributes https: //docs.python.org/3/library/logging.html#logrecord-attributes. Czy istnieje sposób na włączenie strefy czasowej (% z)? ... Czasy formatu ISO8601 w logach Pythona (, ->.) Byłyby świetne. –

+4

To rozwiązanie jest upośledzone, ponieważ jeśli masz '% z' lub'% Z' w swoim 'datefmt', które chcesz, aby pojawiły się PO msecs, nie wcześniej. – wim

+0

A także, jeśli używasz zegara 12-godzinnego, który ma "AM" lub "PM" –

4

Po utworzeniu obiektu Formatter zwykle ustawiony formatter.converter = gmtime. Tak, aby odpowiedź @ unutbu do pracy w tym przypadku trzeba:

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

Najprostszym sposobem znalazłem przesłonić default_msec_format:

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

Interesujące, dzięki. Ale to nie działało dla mnie w Pythonie 2.7. Może działać tylko w Pythonie 3.x dla pewnej wartości x. – nealmcb

1

Prosta rozbudowa które nie wymagają datetime moduł i nie jest utrudniona jak w niektórych innych rozwiązań jest użycie prostego zastąpienia ciąg tak:

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 

ten sposób format daty może być napisany jednak wan t, nawet pozwalając na różnice między regionami, przez użycie milisekund.Na przykład:

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 
0

Jeśli używasz arrow lub jeśli nie masz nic przeciwko użyciu strzałki. Możesz zamienić formatowanie czasu Pythona na strzałkę.

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) 

Teraz możesz korzystać ze wszystkich arrow's time formatting w atrybucie datefmt.

Powiązane problemy