141

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

これが私が知っていることです:

  1. 関数名を取得するために使用できますfunction_name.__name__が、function_name を使用したくありません (Log.info("Message")すべての関数の本体にジェネリックをすばやくコピーして貼り付けることができるようにするため)。これはマクロを使用してCで実行できることは知っていますが__func__、Pythonについてはわかりません。

  2. ファイル名と行番号を取得するために、アプリケーションがPython関数を使用していることがわかりました(そして、私はそれを信じています)locals()が、完全に認識していない構文でoptions = "LOG.debug('%(flag)s : %(flag_get)s' % locals())使用してLOG.info("My message %s" % locals())います{'self': <__main__.Class_name object at 0x22f8cd0>}。これについて何か意見はありますか?

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

助けていただければ幸いです。

ありがとう!

4

4 に答える 4

639

これに対する正解は、すでに提供されているfuncName変数を使用することです

import logging
logger = logging.getLogger(__name__)
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>]]
于 2013-11-21T04:28:35.840 に答える
39

ここには、わずかに関連する質問がいくつかあります。

最も簡単な (3) から始めます。を使用loggingすると、すべての呼び出しを単一のログ ファイルまたはその他の出力ターゲットに集約できます。それらは、プロセスで発生した順序になります。

次は (2)。locals()現在のスコープの辞書を提供します。したがって、他の引数を持たないメソッドではself、現在のインスタンスへの参照を含むスコープ内にあります。あなたを困惑させている使用されているトリックは、dictを%演算子のRHSとして使用する文字列のフォーマットです。"%(foo)s" % barの値が何であれ置き換えられますbar["foo"]

pdb最後に、より多くの情報をログに記録するために使用されるものと同様の、いくつかのイントロスペクション トリックを使用できます。

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
    ))

これにより、渡されたメッセージに加えて、(元の) 関数名、定義が表示されるファイル名、およびそのファイル内の行がログに記録されます。詳細については、inspect - Inspect live objectsを参照してください。

以前のコメントで述べたように、行を挿入してプログラムを再実行するpdbことで、いつでもインタラクティブなデバッグ プロンプトにドロップすることもできます。import pdb; pdb.set_trace()これにより、コードをステップ実行して、選択したデータを検査できます。

于 2012-06-11T04:29:29.937 に答える