Pythonロギングが何も出力しない


94

私が書いているpythonスクリプトで、ロギングモジュールを使用してイベントをログに記録しようとしています。ロガーを構成する次のコードがあります。

ERROR_FORMAT = "%(levelname)s at %(asctime)s in %(funcName)s in %(filename) at line %(lineno)d: %(message)s"
DEBUG_FORMAT = "%(lineno)d in %(filename)s at %(asctime)s: %(message)s"
LOG_CONFIG = {'version':1,
              'formatters':{'error':{'format':ERROR_FORMAT},
                            'debug':{'format':DEBUG_FORMAT}},
              'handlers':{'console':{'class':'logging.StreamHandler',
                                     'formatter':'debug',
                                     'level':logging.DEBUG},
                          'file':{'class':'logging.FileHandler',
                                  'filename':'/usr/local/logs/DatabaseUpdate.log',
                                  'formatter':'error',
                                  'level':logging.ERROR}},
              'root':{'handlers':('console', 'file')}}
logging.config.dictConfig(LOG_CONFIG)

を実行しようとするlogging.debug("Some string")、ドキュメントのこのページでlogging.debugルートロガーがメッセージを出力する必要があると記載されているにもかかわらず、コンソールに出力がありません。プログラムが何も出力しないのはなぜですか、どうすれば修正できますか?

回答:


98

デフォルトのログレベルは警告です。レベルを変更していないため、ルートロガーのレベルはまだ警告のままです。つまり、デバッグログを含め、警告よりも低いレベルのログは無視されます。

これはチュートリアルで説明されています:

import logging
logging.warning('Watch out!') # will print a message to the console
logging.info('I told you so') # will not print anything

レベルが情報よりも高いため、「情報」行は何も出力しません。

レベルを変更するには、それをルートロガーに設定するだけです:

'root':{'handlers':('console', 'file'), 'level':'DEBUG'}

つまり、level = DEBUGでハンドラーを定義するだけでは不十分です。実際のロギングレベルも、何かを出力させるためにDEBUGである必要があります。


6
ドキュメントによると、デフォルトのレベルはNOTSETであり、レベル0ですべてを出力するはずです...なぜこれが真実ではないのですか?
ベン

@ベンどこに言ってるの?私が見ることができるのは、「デフォルトのレベルは警告です。つまり、ロギングパッケージが他の方法で実行するように構成されていない限り、このレベル以上のイベントのみが追跡されます。」
Omri Barel


1
@Benのドキュメントによれば、ロガーは、最初の親level != NOTSETまたはルート(見つからない場合)を見つけるために走査されます。ルートにはWARNINGデフォルトでレベルがあります。これは、リンクしたセクションに記述されています(Logger.setLevel)。
Omri Barel

5
インポート後、少なくとも1回はlogging呼び出す必要があることに注意してくださいlogging.basicConfig()。そうしないと、子ロガーが何も印刷しないことにひどく驚くかもしれません。ルートロガーのロギング機能はそれを遅延的に呼び出します。
Hubert Grzeskowiak

58

それから何年経っても、Pythonロガーにはまだユーザビリティの問題があるようです。以下に例を挙げて説明します。

import logging
# This sets the root logger to write to stdout (your console).
# Your script/app needs to call this somewhere at least once.
logging.basicConfig()

# By default the root logger is set to WARNING and all loggers you define
# inherit that value. Here we set the root logger to NOTSET. This logging
# level is automatically inherited by all existing and new sub-loggers
# that do not set a less verbose level.
logging.root.setLevel(logging.NOTSET)

# The following line sets the root logger level as well.
# It's equivalent to both previous statements combined:
logging.basicConfig(level=logging.NOTSET)


# You can either share the `logger` object between all your files or the
# name handle (here `my-app`) and call `logging.getLogger` with it.
# The result is the same.
handle = "my-app"
logger1 = logging.getLogger(handle)
logger2 = logging.getLogger(handle)
# logger1 and logger2 point to the same object:
# (logger1 is logger2) == True


# Convenient methods in order of verbosity from highest to lowest
logger.debug("this will get printed")
logger.info("this will get printed")
logger.warning("this will get printed")
logger.error("this will get printed")
logger.critical("this will get printed")


# In large applications where you would like more control over the logging,
# create sub-loggers from your main application logger.
component_logger = logger.getChild("component-a")
component_logger.info("this will get printed with the prefix `my-app.component-a`")

# If you wish to control the logging levels, you can set the level anywhere 
# in the hierarchy:
#
# - root
#   - my-app
#     - component-a
#

# Example for development:
logger.setLevel(logging.DEBUG)

# If that prints too much, enable debug printing only for your component:
component_logger.setLevel(logging.DEBUG)


# For production you rather want:
logger.setLevel(logging.WARNING)

混乱の一般的な原因は、初期化が不十分なルートロガーにあります。このことを考慮:

import logging
log = logging.getLogger("myapp")
log.warning("woot")
logging.basicConfig()
log.warning("woot")

出力:

woot
WARNING:myapp:woot

ランタイム環境とロギングレベルによっては、最初のログ行(基本構成の前)がどこにも表示されない場合があります


ログが出力ファイルを生成しないという点で機能していません。私がやっていることは明らかに間違っていると思いますか?logging.basicConfig( filename='logging.txt', level=logging.DEBUG) logger = logging.getLogger() logger.info('Test B') logging.info('Test A')
Rylan Schaeffer

ログファイルは作成されません
Rylan Schaeffer

logger = logging.getLogger()にブレークポイントをドロップすると、レベルをに指定しても、レベルがWARNINGに設定されていることに気付きましたDEBUG。私が間違っていることを知っていますか?
Rylan Schaeffer

こんにちは@RylanSchaeffer、新しい質問を作成し、いくつかの詳細を提供することができます。これはまた、他の人にあなたを助ける機会を与えます。
Hubert Grzeskowiak

やった。多くの場合、少なくとも1人の知識のある人が私の質問を見るので、コメントを求める方が答えを見つけるためのより速い方法です
Rylan Schaeffer

20

超簡単な答えを求めているここの誰にとっても:あなたが表示したいレベルを設定するだけです。私のすべてのスクリプトの一番上に、私は単に入れました:

import logging
logging.basicConfig(level = logging.INFO)

次に、そのレベル以上のものを表示します。

logging.info("Hi you just set your fleeb to level plumbus")

ログはあなたが設定したレベル、またはで表示されるようにこれは、5段階の階層的なセットです高いです。したがって、エラーを表示したい場合は、を使用できますlogging.error("The plumbus is broken")

重要度の昇順でレベルが、あるDEBUGINFOWARNINGERROR、とCRITICAL。デフォルト設定はWARNINGです。

これは私の回答よりもよく表現されたこの情報を含む良い記事です:https :
//www.digitalocean.com/community/tutorials/how-to-use-logging-in-python-3


14

たぶんこれを試してみませんか?私の場合、すべてのハンドラを削除すると問題は解決したようです。

for handler in logging.root.handlers[:]:
    logging.root.removeHandler(handler)

logging.basicConfig(filename='output.log', level=logging.INFO)

SyntaxError: invalid syntax
エリック

2
なぜこれが必要なのですか?pythonロガーにはどのハンドラーが付属していますか。そもそもなぜそこにあるのですか?または、多分問題は、basicConfigがなぜそれらをオーバーライド/置き換えないのですか?
jrh
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.