web-dev-qa-db-ja.com

メインFlaskモジュールの外部でログを記録するにはどうすればよいですか?

私はPython Flaskアプリケーションを持っています。エントリファイルは、次のようにアプリのロガーを構成します。

_app = Flask(__name__)
handler = logging.StreamHandler(sys.stdout)
app.logger.addHandler(handler)
app.logger.setLevel(logging.DEBUG)
_

次に、以下を使用して一連のロギングを行います

app.logger.debug("Log Message")

これは正常に動作します。ただし、次のようないくつかのAPI関数があります。

_@app.route('/api/my-stuff', methods=['GET'])
def get_my_stuff():
    db_manager = get_manager()
    query = create_query(request.args)

    service = Service(db_manager, query)
    app.logger.debug("Req: {}".format(request.url))
_

私が知りたいのは、そのServiceモジュール/ pythonクラス内でロギングを行う方法です。アプリを渡す必要がありますか?これは悪い習慣のようですが、メインのFlaskファイルの外からapp.loggerへのハンドルを取得する方法がわかりません...

23
user4184113

これは重複の可能性がありますが、pythonロギングの知識の小さなビットを書きたいと思います。

ロガーを渡さないでください。 logging.getLogger(<log name as string>)を使用すると、任意のロガーにいつでもアクセスできます。デフォルトでは次のようになります* flaskは、Flaskクラスに指定した名前を使用します。

したがって、メインモジュールが「my_tool」と呼ばれる場合、Serviceモジュールでlogger = logging.getLogger('my_tool')を実行する必要があります。

それに加えて、ロガーとパッケージの命名について明示的にしたいので、Flask('my_tool') **を実行し、他のモジュールでは、サブレベルのロガーを使用します。 logger = logging.getLogger('my_tool.services')すべて同じルートロガー(およびハンドラー)を使用します。

*他の回答に基づく経験なし。

**繰り返しになりますが、フラスコは使用しないでください。DKが適切な場合は使用してください。

編集:超シンプルな愚かな例

メインFlaskアプリ

_import sys
import logging

import flask

from module2 import hi

app = flask.Flask('tester')

handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(logging.Formatter(
    '%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
app.logger.addHandler(handler)
app.logger.setLevel(logging.DEBUG)

@app.route("/index")
def index():
    app.logger.debug("TESTING!")
    hi()
    return "hi"

if __name__ == '__main__':
    app.run()
_

module2

_import logging

log = logging.getLogger('tester.sub')


def hi():
    log.warning('warning test')
_

出力

_127.0.0.1 - - [04/Oct/2016 20:08:29] "GET /index HTTP/1.1" 200 -
2016-10-04 20:08:29,098 - tester - DEBUG - TESTING!
2016-10-04 20:08:29,098 - tester.sub - WARNING - warning test
_

編集2:サブロガーによる混乱

一般的な知識のためだけに、まったく必要ありません。

子ロガーを定義することにより、logging.getLogger('root.something')のルートロガー名の後に_.something_を追加することで、基本的には異なる名前空間を操作できます。

個人的には、ログ機能をグループ化するために使用するのが好きです。したがって、ログに記録されているコードのタイプを知るために、いくつかの_.tool_または_.db_を用意してください。しかし、これらの子ロガーが独自のハンドラーを持つことができるようにすることもできます。したがって、コードの一部のみをstderrまたはログに出力する場合は、そうすることができます。以下は、変更された_module2_の例です。

module2

_import logging
import sys

log = logging.getLogger('tester.sub')
handler = logging.StreamHandler(sys.stderr)
handler.setFormatter(logging.Formatter('%(name)s - %(levelname)s - %(message)s'))
log.addHandler(handler)
log.setLevel(logging.INFO)


def hi():
    log.warning("test")
_

出力

_127.0.0.1 - - [04/Oct/2016 20:23:18] "GET /index HTTP/1.1" 200 -
2016-10-04 20:23:18,354 - tester - DEBUG - TESTING!
tester.sub - WARNING - test
2016-10-04 20:23:18,354 - tester.sub - WARNING - test
_
24
CasualDemon