特殊なloggerとは?
loggingと言えばlogging.iniとかloggingConfigDictとかいろいろあるけど、
例えば、googleのCloud LoggingとかにAI Platformのログを貯めたい時にこんな書き方をします。
import logging
import google.cloud.logging_v2
from google.cloud.logging_v2.handlers import CloudLoggingHandler
from google.cloud.logging_v2.resource import Resource
client = google.cloud.logging_v2.Client(project=os.environ["PROJECT_ID"])
handler = CloudLoggingHandler(client, resource=Resource(
"ml_job",
{
"task_name": "hoge",
"project_id": os.environ["PROJECT_ID"],
"job_id": os.environ["CLOUD_ML_JOB_ID"]
}
)
)
LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.INFO)
LOGGER.addHandler(handler)
ちょっとこれはlogging.iniに書けんなーと思って、
だけどちゃんとモジュールを呼んだらLoggingして欲しい訳です。結構苦しみましたが、うまく動作した例を紹介します。
成功例
以下のようにファイルを整理
from logger import get_logger, set_logger
from module import module
set_logger()
LOGGER = get_logger()
def another():
LOGGER.info("another")
def main():
LOGGER.info("start")
another()
module()
LOGGER.info("end")
if __name__ == "__main__":
main()
from logger import get_logger
# 呼び出したいモジュール
def module():
global LOGGER
LOGGER = get_logger()
LOGGER.info("test")
module2()
def module2():
LOGGER.info("test2")
import logging
def set_logger():
global LOGGER
LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(logging.INFO)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(levelname)s - %(message)s")
ch.setFormatter(formatter)
LOGGER.addHandler(ch)
#今回は簡単な例としてStreamHandlerを使用。
def get_logger():
return LOGGER
まず説明すると、Entrypointとなるmain.pyには必ずset_logger()
を付け加えます。
するとlogger側でLOGGERの設定ができる事になります。
そして、get_logger()
からLOGGERを取り出し、使用することができます。
ここまでは、単純なloggingと変わりません。
問題は別モジュールを呼び出した時、Entrypointで設定したLOGGERはどうやっても読めませんし、
かと言ってもう一度宣言をすると、二重でログを吐くことが分かっています。
なので、モジュールにおいては、get_logger()
だけを使用し、そのLOGGERをGrobal設定することで、
モジュールファイル内のLOGGER全てで設定したLOGGERを使用することができます。
別の方法
別の方法があれば教えてください...もっと...もっと簡潔に書きたい...
参考文献
(あまり参考にできなかったですが、以下の方法もあるみたいです)