アプリケーションがより複雑になるにつれて、 良い ログは、デバッグ時だけでなく、アプリケーションの問題やパフォーマンスに関する洞察を提供する場合にも非常に役立ちます。
Python標準ライブラリには ロギング 基本的なロギング機能のほとんどを提供するモジュール。正しく設定することにより、ログメッセージは、ログがいつどこで発生したか、および実行中のプロセス/スレッドなどのログコンテキストに関する多くの有用な情報をもたらすことができます。
ペン先ファイルとは
利点にもかかわらず、ロギングモジュールは、適切にセットアップするのに時間がかかるため、見過ごされがちです。完全ではありますが、私の意見では、公式のロギングドキュメントは https://docs.python.org/3/library/logging.html ロギングのベストプラクティスを実際に提供したり、ロギングの驚きを強調したりすることはありません。
このPythonロギングチュートリアルは、ロギングモジュールに関する完全なドキュメントではなく、ロギングの概念と注意すべき「落とし穴」を紹介する「はじめに」ガイドを目的としています。投稿はベストプラクティスで終わり、より高度なロギングトピックへのポインタが含まれています。
投稿内のすべてのコードスニペットは、ロギングモジュールをすでにインポートしていることを前提としていることに注意してください。
import logging
このセクションでは、ロギングモジュールでよく見られるいくつかの概念の概要を説明します。
ログレベルは、ログに与えられる「重要性」に対応します。「エラー」ログは「警告」ログよりも緊急である必要がありますが、「デバッグ」ログはアプリケーションをデバッグする場合にのみ役立ちます。
Pythonには6つのログレベルがあります。各レベルは、ログの重大度を示す整数(NOTSET = 0、DEBUG = 10、INFO = 20、WARN = 30、ERROR = 40、およびCRITICAL = 50)に関連付けられています。
cssでflexboxを使用する方法
すべてのレベルはかなり単純です(DEBUG ログフォーマッタは基本的に、コンテキスト情報を追加することでログメッセージを充実させます。ログがいつ送信されるか、どこに送信されるか(Pythonファイル、行番号、メソッドなど)、およびスレッドやプロセスなどの追加のコンテキスト(マルチスレッドアプリケーションをデバッグするときに非常に役立ちます)を知ると便利です。 たとえば、ログ「helloworld」がログフォーマッタを介して送信される場合: になります ログハンドラーは、ログを効果的に書き込み/表示するコンポーネントです。コンソール(StreamHandlerを介して)、ファイル(FileHandlerを介して)、またはSMTPHandlerなどを介して電子メールを送信することによってログを表示します。 各ログハンドラーには、2つの重要なフィールドがあります。 標準ライブラリは、一般的なユースケースに十分な数のハンドラーを提供します。 https://docs.python.org/3/library/logging.handlers.html#module-logging.handlers 。最も一般的なものはStreamHandlerとFileHandlerです。 ロガーは、おそらくコードで最も頻繁に直接使用されるものであり、最も複雑でもあります。新しいロガーは次の方法で入手できます。 ロガーには3つの主要なフィールドがあります。 ロガーは ユニーク 名前で、つまり「toto」という名前のロガーが作成されている場合、結果として ご想像のとおり、ロガーには階層があります。階層の最上位にはルートロガーがあり、logging.rootからアクセスできます。このロガーは、 デフォルトでは、新しいロガーが作成されると、その親はルートロガーに設定されます。 ただし、ロガーは「ドット表記」を使用します。つまり、「a.b」という名前のロガーは、ロガー「a」の子になります。ただし、これはロガー「a」が作成されている場合にのみ当てはまります。それ以外の場合は、「ab」の親がルートのままです。 ロガーがレベルチェックに従ってログに合格するかどうかを決定する場合(たとえば、ログレベルがロガーレベルよりも低い場合、ログは無視されます)、実際のレベルではなく「有効レベル」を使用します。レベルがNOTSETでない場合、つまりDEBUGからCRITICALまでのすべての値の場合、有効レベルはロガーレベルと同じです。ただし、ロガーレベルがNOTSETの場合、有効なレベルは、NOTSET以外のレベルを持つ最初の祖先レベルになります。 デフォルトでは、新しいロガーにはNOTSETレベルがあり、ルートロガーにはWARNレベルがあるため、ロガーの有効レベルはWARNになります。したがって、新しいロガーにいくつかのハンドラーが接続されている場合でも、ログレベルがWARNを超えない限り、これらのハンドラーは呼び出されません。 デフォルトでは、ログの通過を決定するためにロガーレベルが使用されます。ログレベルがロガーレベルよりも低い場合、ログは無視されます。 ロギングモジュールは確かに非常に便利ですが、最高の状態でも長時間の頭痛を引き起こす可能性のあるいくつかの癖が含まれています Python 開発者。私の意見では、このモジュールを使用するためのベストプラクティスは次のとおりです。 新しいロガーを作成して使用できるようになったら、次のようにします。 より多くのベストプラクティスに興味がある場合は、 Python開発者が犯す10の最も一般的な間違い 仲間のApeeScapeerMartinChikilianによる。 デバッグツールは、開発者がエラーを見つけて問題を調査できるようにするツールです。 gdb、pdb(Pythonの場合)などのコマンドラインツールにすることも、IDE(Visual Studio、アイデアスイートなど)に埋め込むこともできます。 これは単にプログラムの出力であり、素人の言葉で言うと「印刷」のより良いバージョンです。 Webアプリケーションのコンテキストでは、このログには通常、要求パス、要求時間、HTTPステータスなどの受信要求情報が含まれます。 ロギングはPython標準ライブラリのモジュールであり、柔軟なフィルターを備えた豊富な形式のログと、syslogや電子メールなどの他のソースにログをリダイレクトする可能性を提供します。 最も人気のあるPythonデバッガーはpdbです。現在、タブ補完、色構文、コードブラウジング、またはリモートデバッグを提供することにより、pdbの使いやすさを向上させるために取り組んでいるプロジェクトがいくつかあります。これらのプロジェクトには、ipdb、pudb、およびwdbが含まれます。 pydevエンジンやPTVSなどのIDE固有のデバッガーもいくつかあります。Pythonロギングフォーマット
'%(asctime)s — %(name)s — %(levelname)s — %(funcName)s:%(lineno)d — %(message)s'
2018-02-07 19:47:41,864 - a.b.c - WARNING - :1 - hello world
Pythonロギングハンドラー
console_handler = logging.StreamHandler() file_handler = logging.FileHandler('filename')
Pythonロガー
次の式のうち、需要の価格弾力性に有効なものはどれですか?
toto_logger = logging.getLogger('toto')
logging.getLogger('toto')
が呼び出されます。同じオブジェクトを返します:assert id(logging.getLogger('toto')) == id(logging.getLogger('toto'))
logging.debug()
のようなメソッドのときに呼び出されます。使用されている。デフォルトでは、ルートログレベルはWARNであるため、レベルが低いすべてのログ(たとえば、logging.info('info')
経由)は無視されます。ルートロガーのもう1つの特徴は、WARNより大きいレベルのログが最初にログに記録されたときにデフォルトのハンドラーが作成されることです。 logging.debug()
などの方法を介して直接または間接的にルートロガーを使用する通常はお勧めしません。各ユニットは、のフォーマットを作成します
lab = logging.getLogger('a.b') assert lab.parent == logging.root # lab's parent is indeed the root logger
la = logging.getLogger('a') assert lab.parent == la # lab's parent is now la instead of root
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
Pythonロギングのベストプラクティス
logging.info()
のような関数を呼び出さないでください。この関数は、実際にはバックグラウンドでルートロガーを呼び出します。使用しているライブラリからのエラーメッセージをキャッチしたい場合は、たとえば、デバッグを容易にするために、ファイルに書き込むようにルートロガーを構成してください。デフォルトでは、ルートロガーはstderr
にのみ出力するため、ログは簡単に失われる可能性があります。logging.getLogger(logger name)
を使用して新しいロガーを作成してください。私は通常__name__
を使用しますロガー名として使用できますが、一貫性がある限り、何でも使用できます。さらにハンドラーを追加するために、私は通常、ロガーを返すメソッドを持っています(要点は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')
基本を理解する
デバッグツールとは何ですか?
デバッグログとは何ですか?
Pythonの「ロギング」とは何ですか?
Pythonデバッガーとは何ですか?