पायथन लॉगिंग: समय प्रारूप में मिलीसेकंड का उपयोग करें


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) मैं मिलीसेकंड और बी को प्राथमिकता दूंगा) निम्नलिखित पायथन 2.6 (जो मैं काम कर रहा हूं) पर काम नहीं करता है %f:

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

1
शायद स्थान बदलने से मदद मिल सकती है?
पजटन

1
@ पजटन - निम्नलिखित लिंक में यह कहा गया है कि "लोकल जानकारी का उपयोग asctime ()" से नहीं किया जाता है - docs.python.org/library/time.html#time.asctime
जोनाथन

%fअजगर 2.7.9 या 3.5.1 पर काम नहीं करता है
एंटोनी हैचकिंस

4
यहां अच्छी बातचीत। मैं यहां आया क्योंकि loggingदावा करता हूं कि इसका डिफ़ॉल्ट समय प्रारूप आईएसओ 8601 है। यह नहीं है। यह अंतरिक्ष का उपयोग करता है, अलग-अलग समय के लिए "T" नहीं और आंशिक बिंदु के लिए अल्पविराम, दशमलव बिंदु नहीं। वे इतने गलत कैसे हो सकते हैं?
एलएस

जवाबों:


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कारण निश्चित नहीं किया जा सकता क्योंकि cta है time.struct_timeऔर ये वस्तुएं मिलीसेकंड रिकॉर्ड नहीं करती हैं।

यदि हम ctइसे बनाने की परिभाषा बदलते हैं तो datetimeइसके बजाय इसे एक वस्तु बना सकते हैं struct_time, (कम से कम पायथन के आधुनिक संस्करणों के साथ) जिसे हम कॉल कर सकते हैं ct.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 वास्तव में माइक्रोसेकंड देगा, मिलीसेकंड नहीं, सही?
जोनाथन

@ जोनाथन: उफ़, आप सही हैं, %fमाइक्रोसेकंड देता है। मुझे लगता है कि मिलीसेकंड प्राप्त करने का सबसे आसान तरीका अल्पविराम को दशमलव बिंदु में बदलना है (ऊपर संपादित देखें)।
अनुतु

3
मुझे वास्तव में लगता है कि यह इस तथ्य के कारण सबसे अच्छा जवाब है कि यह आपको स्टेंडर्ड फॉर्मेटिंग विकल्पों का उपयोग करने में सक्षम होने के लिए सही है। मैं वास्तव में माइक्रोसेकंड चाहता था, और यह एकमात्र विकल्प था जो यह कर सकता था!
14

धन्यवाद। यह उत्तर माइक्रोसेकंड प्राप्त करने के लिए एक आसान समाधान देता है।
योंगवेई वू

337

यह भी काम करना चाहिए:

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

12
धन्यवाद: यहाँ इन के लिए डॉक्स हैं: docs.python.org/2/library/log.html#logrecord-attributes docs.python.org/3/library/log.html#logrecord-attributes । क्या इसका कोई तरीका है अभी भी समय क्षेत्र (% z) शामिल हैं? ... पायथन लॉग में ISO8601 प्रारूप बार (, ->।) बहुत अच्छा होगा।
वेस टर्नर

19
यह समाधान विकलांग है, अगर आपके पास क्योंकि %zया %Zअपने में datefmtआपको लगता है कि msecs के बाद प्रकट करने के लिए, इससे पहले कि नहीं चाहते हैं।
विम

1
और यह भी आप एक 12 घंटे की घड़ी जो प्रयोग कर रहे हैं AMयाPM
DollarAkshay

1
@ मेरी पिछली टिप्पणी के अनुवर्ती के रूप में (अब और संपादन नहीं कर सकता ...), यहाँ मैंने क्या किया है: 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
@ मर्क आप टाइम ज़ोन को default_msec_format(पाइथन 3.7 के रूप में) एम्बेड नहीं कर सकते हैं क्योंकि केवल समय और मिलीसेकंड को loggingस्रोत से बनाया गया है:self.default_msec_format % (t, record.msecs)
एम। डडले

27

Msecs जोड़ना बेहतर विकल्प था, धन्यवाद। यहाँ ब्लेंडर में पायथन 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/log.html#logrecord-attributes
naphier

हम्म दिलचस्प बिंदु, टिप्पणी के लिए धन्यवाद यह निश्चित रूप से विचार के लिए भोजन है। हां, मैंने शायद इसे एक सबक के रूप में जोड़ा है जो वहां भी चल रहा है, और यह सुनिश्चित करने के लिए कि यह वहां है और क्योंकि मैंने कई चीजें पूछी हैं, इसलिए इसे लाने के लिए माता-पिता ('।') को कई कॉल की आवश्यकता नहीं है। यदि आप .info या .debug को फिर से बुलाते हैं, तो मैं शायद उन लोगों को सीधे बचाऊंगा, जैसा कि आप एक रेफरेंस लुक साइकिल को बचाने का सुझाव देते हैं। [जानकारी दें = logging.info]
मास्टर जेम्स

जेसन कहने के लिए धन्यवाद। कभी-कभी दुनिया को देखने का एक सरल तरीका होता है, कोशिश करें और उस सत्य की खोज करने से न डरें यदि कोई नहीं / हर स्थिति में।
मास्टर जेम्स

15

सबसे आसान तरीका जो मुझे मिला वह default_msec_format को ओवरराइड करने का था:

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

1
दिलचस्प है, धन्यवाद। लेकिन यह मेरे लिए पायथन 2.7 में काम नहीं किया। यह केवल x के कुछ मान के लिए पायथन 3.x में काम कर सकता है।
nealmcb


3

तुरंत FormatterI सेट करने के बाद 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

यदि आप तीर का उपयोग कर रहे हैं या यदि आपको तीर का उपयोग करने में कोई आपत्ति नहीं है। आप तीर के एक के लिए अजगर के समय को प्रतिस्थापित कर सकते हैं।

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:

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


-3

अब तक निम्नलिखित अजगर 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 पैडेड के साथ मुद्रित किया गया है।
क्लिक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.