Pythonのログ記録
アプリケーションがより複雑になるので、良いログを持つことは、デバッグ時だけでなく、アプリケーションの問題/パフォーマンスに対する洞察を提供するのに非常に役に立つことができます.ロギングも有名なの要因の一つですThe twelve-factor app .
Python標準ライブラリはlogging 基本的なロギング機能のほとんどを提供するモジュール.正しく設定することにより、ログメッセージは、ログおよびログがどこで実行されるかについての有用な情報をもたらすことができます.
利点にもかかわらず、ロギングモジュールはしばしば、それが適切に設定するのに若干の時間がかかるので、見落とされます.atの公式dochttps://docs.python.org/3/library/logging.html , 完全ですが、ベストプラクティスを与えたり、いくつかのログ記録の驚きを強調表示しません.
このPythonロギングチュートリアルは、ロギングモジュールの完全なドキュメントではなく、いくつかのログの概念を紹介する入門ガイドである.ポストはベストプラクティスで終了します.
ポスト内のすべてのコードスニペットは既にログモジュールをインポートしていると仮定します.
このセクションでは、ロギングモジュールでよく遭遇する概念の概要を示します.
ログレベルはログが与えられる重要度に対応する
Pythonには6つのログレベルがあります.各レベルは、ログの重大度を示す整数に関連付けられています.
ログ
例えば、ログ
ログ
各ログハンドラには2つの重要なフィールドがあります. ログにコンテキスト情報を追加するフォーマッタ. レベルが下位であるログをフィルタリングするログレベル.たとえば、infoレベルのログハンドラは、デバッグログを処理しません. 標準ライブラリは、一般的なユースケースに十分なハンドラを提供します.https://docs.python.org/3/library/logging.handlers.html#module-logging.handlers . 最も一般的なものは
ロガーは、我々は、最も複雑なコンセプトであるほとんどのと対話するオブジェクトです.新しいロガーは次のようにして入手できます.
ロガーは名前によってユニークです.
ルートロガーのもう一つの具体性は、デフォルトのハンドラーがWarnより大きいレベルでログが記録される最初に作成されるということです.ルートロガーを直接、あるいは間接的にメソッドを通して使用する
デフォルトでは、新しいロガーが作成されると、その親はルートロガーに設定されます.
デフォルトでは、新しいロガーは
ログモジュールは本当に便利ですが、それは最高のPython開発者のための頭痛の長い時間を引き起こす可能性がありますいくつかの風変わりが含まれています.私の意見では、このモジュールを使用するための最良のプラクティスです ルートロガーを構成しますが、決してコードのような関数を呼び出すことはありません ログを使用するには、新しいロガーを
用途 自動的にあなたのためにエラーログをキャッチする歩哨、エアブレーキ、レイガンなどのようなツールを使用します.これは特にログが非常に冗長であり、エラーログが簡単に失われることができるWebアプリケーションのコンテキストで有用です.これらのツールを使用するもう1つの利点は、エラーが発生したユーザーの原因となるURLを知ることができるように、エラーの変数値の詳細を取得することです. 確実にログを正しく動作させることは、将来的に数え切れないほどのデバッグ時間を節約することができるので、新しいプロジェクトを設定するときに最初にすべきことの一つであるべきです.
Python標準ライブラリはlogging 基本的なロギング機能のほとんどを提供するモジュール.正しく設定することにより、ログメッセージは、ログおよびログがどこで実行されるかについての有用な情報をもたらすことができます.
利点にもかかわらず、ロギングモジュールはしばしば、それが適切に設定するのに若干の時間がかかるので、見落とされます.atの公式dochttps://docs.python.org/3/library/logging.html , 完全ですが、ベストプラクティスを与えたり、いくつかのログ記録の驚きを強調表示しません.
このPythonロギングチュートリアルは、ロギングモジュールの完全なドキュメントではなく、いくつかのログの概念を紹介する入門ガイドである.ポストはベストプラクティスで終了します.
ポスト内のすべてのコードスニペットは既にログモジュールをインポートしていると仮定します.
import logging
Pythonログの概念
このセクションでは、ロギングモジュールでよく遭遇する概念の概要を示します.
レベル
ログレベルはログが与えられる重要度に対応する
error
それから、ログはより緊急でなければなりませんwarn
ログ、一方でdebug
アプリケーションのデバッグ時にのみログを有効にする必要があります.Pythonには6つのログレベルがあります.各レベルは、ログの重大度を示す整数に関連付けられています.
NOTSET=0, DEBUG=10, INFO=20, WARN=30, ERROR=40, CRITICAL=50.
フォーマッタ
ログ
formatter
それに文脈情報を加えることによって、ログメッセージを豊かにしてください.ログが送られた時、(Pythonファイル、行番号、メソッドなど)、およびスレッドやプロセスIDなどの追加のコンテキストを知るのに便利です.例えば、ログ
hello world
を返します."%(asctime)s — %(name)s — %(levelname)s — %(funcName)s:%(lineno)d — %(message)s"
となる2018-02-07 19:47:41,864 - a.b.c - WARNING - <module>:1 - hello world
ハンドラ
ログ
handler
ログを効果的に書き込む/表示するコンポーネントです.ログをコンソール経由で表示することができますStreamHandler
, 経由でファイルに書き込むFileHandler
, またはもメールを介して送信するSMTPHandler
, など各ログハンドラには2つの重要なフィールドがあります.
StreamHandler
and FileHandler
:console_handler = logging.StreamHandler()
file_handler = logging.FileHandler("filename")
ロガー
ロガーは、我々は、最も複雑なコンセプトであるほとんどのと対話するオブジェクトです.新しいロガーは次のようにして入手できます.
toto_logger = logging.getLogger("toto")
ロガーには三つの主要なフィールドがあります.Propagate
: ログがロガーの親に伝播されるかどうかを調べます.デフォルトではTrue
. Level
: ハンドラーレベルのように、ロガーレベルは、より重要なログを除外するために使用されます.ログハンドラとは異なり、レベルは子ロガーでのみチェックされます.ログが親に伝播されると、レベルはチェックされません.これはむしろ直感的な行動です.Handlers
: ロガーに到着するときにログが送られるハンドラのリスト.これにより、柔軟なログ処理を可能にします.たとえば、すべてのデバッグログをログ出力するファイルログハンドラと、重要なログにのみ使用される電子メールログハンドラを持つことができます.この点に関して、ロガーハンドラ関係は出版者消費者1に類似しています:ログがloggerレベルチェックを通過するならば、ログはすべてのハンドラに放送されます.ロガーは名前によってユニークです.
toto
が生成された、その結果としての呼び出しlogging.getLogger("toto")
は同じオブジェクトを返します:assert id(logging.getLogger("toto")) == id(logging.getLogger("toto"))
あなたが推測したかもしれないように、ロガーには階層があります.階層の上にroot
ロガーは、logging.root
. このロガーは、メソッドがlogging
例えばモジュールです.logging.debug()
. デフォルトでは、ルートログレベルはWARN
, したがって、低レベルですべてのログ、例えばlogging.info("info")
, は無視される.ルートロガーのもう一つの具体性は、デフォルトのハンドラーがWarnより大きいレベルでログが記録される最初に作成されるということです.ルートロガーを直接、あるいは間接的にメソッドを通して使用する
logging.debug()
は一般に推奨されない.デフォルトでは、新しいロガーが作成されると、その親はルートロガーに設定されます.
lab = logging.getLogger("a.b")
assert lab.parent == logging.root # lab's parent is indeed the root logger
しかし、ロガーはドット表記を使用しますa.b
ロガーの子になりますa
. しかし、これはLoggera
が作成されていなければab
親はまだroot
ロガー.la = logging.getLogger("a")
assert lab.parent == la # lab's parent is now la instead of root
ロガーがレベルチェック(例えばログレベルがロガーレベルより低いならば、ログが無視される)によって通過するべきであるかどうかを決定するとき、それは実際のレベルの代わりにその有効なレベルを使用します.logger.level
. レベルがそうでないならば、有効なレベルはロガーレベルと同じですNOTSET
, つまり、デバッグからデバッグまでのすべての値しかし、ロガーレベルがNOTSET
, 次に、無効なレベルを持つ最初の祖先レベルが有効レベルになります.デフォルトでは、新しいロガーは
NOTSET
ルートロガーとしてWARN
レベル、ロガーの効果的なレベルが警告されます.新しいロガーが何らかのハンドラを接続していても、ログレベルが警告を超えない限り、これらのハンドラは呼び出されません.toto_logger = logging.getLogger("toto")
assert toto_logger.level == logging.NOTSET # new logger has NOTSET level
assert toto_logger.getEffectiveLevel() == logging.WARN # and its effective level is the root logger level, i.e. WARN
# attach a console handler to toto_logger
console_handler = logging.StreamHandler()
toto_logger.addHandler(console_handler)
toto_logger.debug("debug") # nothing is displayed as the log level DEBUG is smaller than toto effective level
toto_logger.setLevel(logging.DEBUG)
toto_logger.debug("debug message") # now you should see "debug message" on screen
デフォルトではlogger
ログレベルがloggerレベルより低い場合、ログは無視されます.Pythonログのベストプラクティス
ログモジュールは本当に便利ですが、それは最高のPython開発者のための頭痛の長い時間を引き起こす可能性がありますいくつかの風変わりが含まれています.私の意見では、このモジュールを使用するための最良のプラクティスです
logging.info()
, これは、シーンの背後にルートロガーを呼び出します.rootロガーの設定は、使用しているライブラリからエラーメッセージをキャッチしたい場合に便利です.logging.getLogger(logger name)
. 通常使用__name__
個々のモジュールのロガー名または全体のアプリケーション/libの静的な名前として、それは一貫している限り、何かを使用することができます.より多くのハンドラを追加するには、通常、ロガーを返すメソッドがありますhttps://gist.github.com/nguyenkims/e92df0f8bd49973f0c94bddf36ed7fd0 ).import logging
import sys
from logging.handlers import TimedRotatingFileHandler
FORMATTER = logging.Formatter("%(asctime)s — %(name)s — %(levelname)s — %(message)s")
LOG_FILE = "my_app.log"
def get_console_handler():
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(FORMATTER)
return console_handler
def get_file_handler():
file_handler = TimedRotatingFileHandler(LOG_FILE, when='midnight')
file_handler.setFormatter(FORMATTER)
return file_handler
def get_logger(logger_name):
logger = logging.getLogger(logger_name)
logger.setLevel(logging.DEBUG) # better to have too much log than not enough
logger.addHandler(get_console_handler())
logger.addHandler(get_file_handler())
# with this pattern, it's rarely necessary to propagate the error up to parent
logger.propagate = False
return logger
新しいロガーを作成し、それを使うことができます.my_logger = get_logger("my module name")
my_logger.debug("a debug message")
RotatingFileHandler
などのクラスTimedRotatingFileHandler
代わりに例で使用するFileHandler
, ファイルがサイズ制限に達したとき、自動的にあなたのためにファイルを回転させるか、毎日それをしてください.Reference
この問題について(Pythonのログ記録), 我々は、より多くの情報をここで見つけました https://dev.to/simplelogin/python-logging-an-in-depth-tutorial-f15テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol