Pythonロギング:時間形式でミリ秒を使用


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)ミリ秒が好きです%f

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

1
多分ロケールを変更すると役立つでしょうか?
pajton

1
@ pajton-次のリンクでは、「ロケール情報はasctime()では使用されません」と表示されています-docs.python.org/library/time.html#time.asctime
Jonathan

%fはPython 2.7.9または3.5.1でも機能しません
Antony Hatchkins

4
ここで良い会話。ここに来たのloggingは、デフォルトの時刻形式がISO 8601に準拠していると主張しているからです。そうではありません。小数点ではなく、小数秒の時間とコンマを区切るために "T"ではなくスペースを使用します。彼らはどうしてそんなに間違っているのでしょうか?
LS

回答:


76

Craig McDanielのソリューションの方が明らかに優れていることに注意してください。


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である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マイクロ秒を与える。ミリ秒を取得する最も簡単な方法は、コンマを小数点に変更することです(上記の編集を参照)。
unutbu

3
STANDARDのフォーマットオプションを使用できるようになるため、これが最良の答えだと思います。私は実際にはマイクロ秒が欲しかったのですが、これがそれを実行できる唯一のオプションでした!
トランペットリック、

ありがとう。この答えは、マイクロ秒を取得する簡単なソリューションを提供します。
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)がまだ含まれていますか?... PythonログのISO8601形式の時間(、->。)はすばらしいでしょう。
ウェスターナー

19
このソリューションはハンディキャップを持っています。なぜなら、あなたが持っている%z%Z、あなたの中にdatefmtそれが前ではなくミリ秒後に表示されることを望むからです。
wim 2017

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(Python 3.7現在)。時間とミリ秒のみが代入されるためです。loggingソースから:self.default_msec_format % (t, record.msecs)
M. Dudley

27

ミリ秒を追加する方が良いオプションでした。ありがとうございます。これはBlenderの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]
マスタージェームズ

ジェイソンを言ってくれてありがとう。時々、世界を見るためのより簡単な方法があります、どんな/すべての状況ではないにせよ多くの状況でその真実を発見しようとすることを恐れないでください。
マスタージェームズ

15

私が見つけた最も簡単な方法はdefault_msec_formatをオーバーライドすることでした:

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

1
興味深い、ありがとう。しかし、これはPython 2.7では機能しませんでした。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ます。



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