2013-04-03 28 views
9

標準の設定はPythonアプリケーション内からのログを実行するためのものであると思っていました。複数のモジュールでPythonのログを使用する方法

Loggingクラスを使用しています.Loggingクラスをインスタンス化する独自のLoggerクラスを作成しました。私のメインは、私のロガーラッパークラスをインスタンス化します。しかし、私のメインは他のクラスをインスタンス化し、それらの他のクラスもメインのロガーオブジェクトを介して彼がログファイルに書き込むことができるようにしたい。

このロガーオブジェクトを他のクラスから呼び出せるようにするにはどうすればよいですか?これを動作させるには、何らかの静的なロガーオブジェクトが必要なのとほとんど同じです。

質問の長短は次のようなものです:main内からインスタンス化されたすべてのクラスが同じログファイルに書き込むことができるように、どのようにコード構造内にログを実装しますか?同じファイルを指す各クラスに新しいロギングオブジェクトを作成するだけですか?

答えて

6

は、あなたのログオブジェクトのインスタンスを取得するにはlogging.getLogger()を使用してみてください。

http://docs.python.org/3/library/logging.html#logging.getLogger

この関数のすべての呼び出しは、指定された名前と同じロガーインスタンスを返します。つまり、アプリケーションの異なる部分間でロガーインスタンスを渡す必要はありません。

UPDATE

これを行うための推奨される方法は、(...など、ハンドラを設定し、フォーマッタ)のgetLogger()関数を使用し、それを設定することです:

# main.py 
import logging 
import lib 


def main(): 
    logger = logging.getLogger('custom_logger') 
    logger.setLevel(logging.INFO) 
    logger.addHandler(logging.FileHandler('test.log')) 
    logger.info('logged from main module') 
    lib.log() 

if __name__ == '__main__': 
    main() 

# lib.py 
import logging 


def log(): 
    logger = logging.getLogger('custom_logger') 
    logger.info('logged from lib module') 

本当にがロガークラスを拡張する必要がある場合logging.setLoggerClass(klass)

UPDATE 2http://docs.python.org/2/howto/logging.html#custom-levels

は、カスタムの定義:カスタムレベルを追加することは推奨されません

# main.py 
import logging 
import lib 


# Extend Logger class 
CUSTOM_LEVEL_NUM = 9 
logging.addLevelName(CUSTOM_LEVEL_NUM, 'CUSTOM') 
def custom(self, msg, *args, **kwargs): 
    self._log(CUSTOM_LEVEL_NUM, msg, args, **kwargs) 
logging.Logger.custom = custom 

# Do global logger instance setup 
logger = logging.getLogger('custom_logger') 
logger.setLevel(logging.INFO) 
logger.addHandler(logging.FileHandler('test.log')) 


def main(): 
    logger = logging.getLogger('custom_logger') 
    logger.custom('logged from main module') 
    lib.log() 

if __name__ == '__main__': 
    main() 

注:ロギングクラスを変更することなく、カスタムログレベルを追加する方法の

例1つ以上のロガーを使用することは、あなたの他の要件のためのトリックを行うかもしれません:オプションの出力を標準エラー出力に出力します。

+0

ここではちょっと密集して申し訳ありません。だから、自分のLogクラス(ログクラスを含む)をインスタンス化するメインモジュールを持っていれば、単にLogオブジェクトを呼び出すだけで簡単にログを記録できます。しかし、私のメインが他のモジュールをインポートする場合、どのようにLogメソッドを呼び出して、すべてのメソッドにログハンドルを渡さずにログを記録するのですか?複数のモジュールを使用した例を提供できますか? – GregH

+0

複数のモジュールとgetLogger()関数を使用した例を提供しました。 Logger(logging.getLoggerClass())クラスを拡張する必要はほとんどありません。実際にgetLoggerを使用してロガーを作成し、カスタムHandlerを設定するとすれば、必要なだけでは十分ではありませんが、カスタムLoggerクラスの背後にある根拠について説明してください。 – gonz

+0

@GregH私の例は理にかなっていますか?それがあなたの問題を解決するか、それ以上の説明が必要かどうかを教えてください。 – gonz

24

Loggingクラスの意味を理解できません。Pythonの組み込みログにはこのようなクラスはありません。あなたは本当にラッパーを必要としない:ここにあなたが書いた任意のクラスからロギングを行う方法の例です:

import logging 

# This class could be imported from a utility module 
class LogMixin(object): 
    @property 
    def logger(self): 
     name = '.'.join([__name__, self.__class__.__name__]) 
     return logging.getLogger(name) 


# This class is just there to show that you can use a mixin like LogMixin 
class Base(object): 
    pass 

# This could be in a module separate from B 
class A(Base, LogMixin): 
    def __init__(self): 
     # Example of logging from a method in one of your classes 
     self.logger.debug('Hello from A') 

# This could be in a module separate from A 
class B(Base, LogMixin): 
    def __init__(self): 
     # Another example of logging from a method in one of your classes 
     self.logger.debug('Hello from B') 

def main(): 
    # Do some work to exercise logging 
    a = A() 
    b = B() 
    with open('myapp.log') as f: 
     print('Log file contents:') 
     print(f.read()) 

if __name__ == '__main__': 
    # Configure only in your main program clause 
    logging.basicConfig(level=logging.DEBUG, 
         filename='myapp.log', filemode='w', 
         format='%(name)s %(levelname)s %(message)s') 
    main() 

一般的に、それはクラスレベルでロガーを持っている必要はありません:Pythonで、たとえばJavaの、ユニットとは異なりプログラム(de)の構成はモジュールです。しかし、私が上に示したように、それをやることを止めるものはありません。スクリプトを実行すると、次のメッセージが表示されます。

Log file contents: 
__main__.A DEBUG Hello from A 
__main__.B DEBUG Hello from B 

両方のクラスのコードが同じファイルmyapp.logに記録されます。これは、AとBが異なるモジュールであっても機能しました。

+0

これは私がPythonでログインするために見た最もエレガントなソリューションです。共有していただきありがとうございます :-) –

関連する問題