2012-06-11 15 views
65

私はアプリケーションの仕組みを学びたいと思っています。そして、このために、関数の名前とログ出力にメッセージを送信する行番号(コード内)を記録する目的で、各関数の本体の最初の行としてデバッグコマンドを挿入しています。最後に、このアプリケーションは多数のファイルで構成されているため、アプリケーションの制御フローをよりよく理解できるように、単一のログファイルを作成したいと考えています。ここで単一ファイルを使用したPythonロギング(関数名、ファイル名、行番号)

は、私が知っているものです:

  1. 関数名を取得するために、私はfunction_name.__name__を使用することができますが、私は私が急速で、一般的なLog.info("Message")をコピーして貼り付けることができるように(FUNCTION_NAMEを使用したくありませんすべての機能の本体)。私はこれがCで__func__マクロを使用して行うことができます知っているが、私はPythonについてはわからない。 options = "LOG.debug('%(flag)s : %(flag_get)s' % locals())と私のような使用して、それを試してみました:私のアプリケーションは、Python locals()機能を使用しているが、私は例えばの完全に認識していないです構文で

  2. は、ファイル名と行番号を取得するために、私はそれを見てきました(と私はそれを信じています) LOG.info("My message %s" % locals())これは{'self': <__main__.Class_name object at 0x22f8cd0>}のようなものを生成します。これで何か入力してください?

  3. ロギングを使用してファイルにログを記録する方法を知っていますが、プロジェクト内の関数呼び出しの正しい順序ですべてのログメッセージを記録するために単一のファイルを使用できるかどうかはわかりません。

私は非常に助けていただければ幸いです。

ありがとうございます!

+0

あなたは 'import pdb;を使ってpythonデバッガに入ることができます。 pdb.set_trace() 'を呼び出し、対話的にコードをステップ実行します。それはプログラムフローをトレースするのに役立ちます。 –

+0

素晴らしいアイデア!マットありがとう。それは私が毎回デバッグする必要はありませんので、質問に記載されているようにログを取得することはまだ役立つでしょう。また、Eclipse用のJavaと同じくらい良いpython用のIDEについて知っていますか(ctrl + clickは関数定義に変わります)、デバッグを簡単にするために使用できますか? – user1126425

答えて

17

ここでは、多少関連性のある質問があります。

私は最も簡単に始めます:(3)。 loggingを使用すると、すべての呼び出しを1つのログファイルまたは他の出力先に集約できます。プロセス内で発生した順番になります。

次のページ:(2)。 locals()は、現在のスコープを示すものです。したがって、他の引数を持たないメソッドでは、範囲内にselfがあり、現在のインスタンスへの参照が含まれています。あなたのおかげで使用されているトリックは、%演算子のRHSとしてdictを使用する文字列の書式設定です。 "%(foo)s" % barは、bar["foo"]の値に置き換えられます。これは、渡されたメッセージを、プラス(本来の)関数名、ファイル名がログに記録されます

def autolog(message): 
    "Automatically log the current function details." 
    import inspect, logging 
    # Get the previous frame in the stack, otherwise it would 
    # be this function!!! 
    func = inspect.currentframe().f_back.f_code 
    # Dump the message + the name of this function to the log. 
    logging.debug("%s: %s in %s:%i" % (
     message, 
     func.co_name, 
     func.co_filename, 
     func.co_firstlineno 
    )) 

最後に、あなたはより多くの情報を記録することができるpdbで使用されるものと同様のいくつかのイントロスペクションのトリックを、使用することができます定義が現れる場所、およびそのファイル内の行詳細はinspect - Inspect live objectsをご覧ください。

前述のように、を挿入してプログラムを再実行することで、いつでも対話型デバッグプロンプトpdbをドロップすることができます。これにより、コードをステップ実行して、選択したとおりにデータを検査することができます。

+0

ありがとうMatt!私はこのautolog機能を試みます。 '%(foo)s:%(bar)s''は' bar ["foo"] 'の値も出力しますか?それともあなたの例とは少し違うのですか? – user1126425

+0

基本的に '%()s'の形式のすべては、dictで参照されているオブジェクトの値に' 'で置き換えられます。 http://docs.python.org/library/stdtypes.html#string-formatting –

+0

にはもっと多くのサンプル/詳細があります@synthesizerpatelの答えははるかに役立ちます。 – Jan

276

このため、正しい答えはすでにどこでもあなたが望む、ちょうど追加しfuncName変数

import logging 
logger = logging.getLogger('root') 
FORMAT = "[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s" 
logging.basicConfig(format=FORMAT) 
logger.setLevel(logging.DEBUG) 

を提供し使用することです:

logger.debug('your message') 

出力例を私は右に取り組んでいるスクリプトから今すぐ:

[invRegex.py:150 -   handleRange() ] ['[A-Z]'] 
[invRegex.py:155 -  handleRepetition() ] [[<__main__.CharacterRangeEmitter object at 0x10ba03050>, '{', '1', '}']] 
[invRegex.py:197 -   handleMacro() ] ['\\d'] 
[invRegex.py:155 -  handleRepetition() ] [[<__main__.CharacterRangeEmitter object at 0x10ba03950>, '{', '1', '}']] 
[invRegex.py:210 -  handleSequence() ] [[<__main__.GroupEmitter object at 0x10b9fedd0>, <__main__.GroupEmitter object at 0x10ba03ad0>]] 
+20

これは答えだったはずです! – user3885927

+1

素晴らしい.. 追加するべきことは、logfileをcodefileと同じにすることができますか? 例: logging.basicConfig(filename = "%(filename)"、format = FORMAT) ファイル名を動的に取得しようとしましたが、静的な値をとりました。なにか提案を? – Outlier

+2

@Outlierいいえ、それを達成するための推奨される方法は 'getLogger(__ name __)'です。 – farthVader

関連する問題