仕事
スクリプトのコレクションがあり、実際のメッセージをログに記録するモジュールへの変更を最小限に抑えて、統合されたログ メッセージを生成するようにしたいと考えています。
メインアプリケーションから一度呼び出す予定の小さなモジュール「custom_logger」を作成しました。ロガーを返し、それを引き続き使用します。
アプリにインポートするサブモジュールは、
- 「ログをログとしてインポート」する必要があります-他の誰かがそれらを有用だと思った場合に実行するために、私のサイトに固有のものは何も必要ありません。
- サイト固有のものを追加せずに、 log.info/error('message') でメッセージをログに記録するだけです
- 構成済みの「ルート」ロガーをすべてのフォーマットとハンドラーと共に使用し、ルート ロガーの構成に影響を与えないようにする必要があります。
*custom_logger.py*
import logging
import logging.handlers
import os
import sys
def getLogger(name='root', loglevel='INFO'):
logger = logging.getLogger(name)
# if logger 'name' already exists, return it to avoid logging duplicate
# messages by attaching multiple handlers of the same type
if logger.handlers:
return logger
# if logger 'name' does not already exist, create it and attach handlers
else:
# set logLevel to loglevel or to INFO if requested level is incorrect
loglevel = getattr(logging, loglevel.upper(), logging.INFO)
logger.setLevel(loglevel)
fmt = '%(asctime)s %(filename)-18s %(levelname)-8s: %(message)s'
fmt_date = '%Y-%m-%dT%T%Z'
formatter = logging.Formatter(fmt, fmt_date)
handler = logging.StreamHandler()
handler.setFormatter(formatter)
logger.addHandler(handler)
if logger.name == 'root':
logger.warning('Running: %s %s',
os.path.basename(sys.argv[0]),
' '.join(sys.argv[1:]))
return logger
次に、何が機能し、何が機能しないかの例を含むいくつかのテスト メッセージを含むサブモジュールが続きます。
submodule.py
import sys
import custom_logger
import logging
class SubClass(object):
def __init__(self):
# NOK (no idea why since by default (no name parameter), it should return the root logger)
#log = logging.getLogger()
#log.info('message from SubClass / __init__')
# OK (works as expected)
#log = logging.getLogger('root')
#log.info('message from SubClass / __init__')
# OK (works as expected)
log = custom_logger.getLogger('root')
log.info('message from SubClass / __init__')
def SomeMethod(self):
# OK but I'd have to define `log` for every method, which is unacceptable
# Please see question below all code snippets
log = custom_logger.getLogger('root')
log.info('message from SubClass / SomeMethod')
そしてメインアプリ: app.pyここには特別なものはありません:
#!/usr/bin/python
import custom_logger
import submodule
log = custom_logger.getLogger('root', loglevel='DEBUG')
log.debug('debug message')
log.info('info message')
log.warning('warning message')
log.error('error message')
a = submodule.SubClass() # this should produce a log message
a.SomeMethod() # so should this
非常に醜い方法で、私が求めている出力と取得している出力:
% ./app.py
2013-04-08T03:07:46BST custom_logger.py WARNING : Running: app.py
2013-04-08T03:07:46BST app.py DEBUG : debug message
2013-04-08T03:07:46BST app.py INFO : info message
2013-04-08T03:07:46BST app.py WARNING : warning message
2013-04-08T03:07:46BST app.py ERROR : error message
2013-04-08T03:07:46BST submodule.py INFO : message from SubClass / __init__
2013-04-08T03:07:46BST submodule.py INFO : message from SubClass / SomeMethod
app.py でロガーを定義し、サブモジュールで標準の Python ログ ライブラリのみを使用して、app.py で既に構成されているロガーを利用できるようにしたいと考えています。
また、醜い回避策: submodule.py のインポートの後に以下のコードを配置すると:
log = custom_logger.getLogger('root')
私のロガーがapp.pyで設定される前に実行され、アプリがロギングを設定するのではなく、サブモジュールを効果的に作成します。
私が検討した別の回避策: SubClass クラスのコンストラクター内で、定義できます
self.log = custom_logger.getLogger('root')
次に、self.log.error('some error') を使用します。もっと良い方法があるに違いありません - 何か役に立つことを提案したり、ドキュメントのどこを誤解したかを指摘したりできれば、とても感謝しています!
PS。私は Python ロギングのハウツー (基本および上級) とクックブックを読むのにかなりの時間を費やしました。
ありがとうございました!