LoginSignup
0
1

More than 3 years have passed since last update.

【Python3】開発で使えるシリーズ その② ログメッセージ

Last updated at Posted at 2019-09-15

テーマ:ログメッセージ

【ポイント】
1. IDからメッセージを取得
2. メッセージに値を埋め込むことが可能
3. メッセージに値を辞書形式で埋め込むことが可能

ディレクトリ

common/
  └ __init__.py
  └ message/
       └ message.py
       └ log_message.csv

tools/
  └ __init__.py
  └ test.py

settings/
  └ __init__.py
  └ settings.py

message/log_message.csv

ID,MESSAGE
D10001,{}処理-START
D10002,{}処理-END
I10001,{}処理-START
I10002,{}処理-END
W10001,{}バージョン以降、使用できなくなります。
E10001,予期せぬエラーが発生しました。{}
I10003,{}第一引数[{param1}]/第二引数[{param2}]を見直してください。
I10004,名前は {last_name} {first_name}. {first_name} {last_name}

settings/settings.py

# メッセージファイルの管理場所を変更したい場合、定義する
MESSAGE_DIR_PATH = None

message/message.py

import os

import pandas as pd


class MessageNotFoundError(Exception):
    def __init__(self, message_id):
        self.message_id = message_id

    def __str__(self):
        return 'メッセージIDが存在しません。[{}]'.format(self.message_id)


class Message(object):
    _message_file_name = 'log_message.csv'

    @classmethod
    def _get_message_file_dir_path(cls):
        """メッセージファイルの絶対パスを取得

        Args:
            None
        Returns:
            file_path: (str): メッセージファイルが存在する絶対パス
        Raise:
            ImportError: setting.pyが作成されていない場合
            AttributeError: setting.pyにMESSAGE_DIR_PATHAが定義されていない場合
            FileNotFoundError: メッセージファイルが存在しない場合
        """
        file_dir_path = None

        try:
            from settings import settings
            if settings.MESSAGE_DIR_PATHA:
                file_dir_path = settings.MESSAGE_DIR_PATH
        except ImportError:
            pass
        except AttributeError:
            pass

        if not file_dir_path:
            file_dir_path = os.path.dirname(os.path.abspath(__file__))

        file_path = os.path.join(file_dir_path, cls._message_file_name)
        if not os.path.exists(file_path):
            raise FileNotFoundError
        return file_path

    @classmethod
    def search_message(cls, message_id):
        """メッセージファイルからmessage_idを探す

        Args:
            message_id: (str): メッセージID
        Resturns:
            message: (str): メッセージIDに紐づくテキスト
        Raise:
            MessageNotFoundError: メッセージIDがメッセージファイルに存在しない場合
        Example:
            >>> # 存在するメッセージIDを指定
            >>> m =Message
            >>> m.search_message('D10001')
            '{}処理-START'

            >>> # 存在しないメッセージを指定
            >>> m.search_message('hogehoge')
            Traceback (most recent call last):
            ...
            MessageNotFoundError: メッセージIDが存在しません。[hogehoge]

        """
        file_path = cls._get_message_file_dir_path()
        messages = pd.read_csv(file_path)
        if message_id not in messages.values:
            raise MessageNotFoundError(message_id)

        row = messages[messages.ID == message_id].MESSAGE
        message = row[row.index[0]]

        del messages
        return message

    @classmethod
    def action_log_message(cls, message_id, *args, **kwargs):
        """ログメッセージを作成する
           引数(*args)が存在する場合、メッセージに引数の値を埋め込む

        Args:
            message_id: (str): log_message.csvで管理されているメッセージID
            *args: (tuple): メッセージに埋め込む用の引数
            **kwargs: (dict): キーバリューで渡ってくるメッセージ埋め込む用の引数
        Returns:
            log_message: (str): ログに出力するメッセージ
        Example:
            >>> m = Message
            >>> # D10001,{}処理-START
            >>> m.action_log_message('D10001', 'Hoge')
            'Hoge処理-START'

            >>> # I10004,名前は {last_name} {first_name}. {first_name} {last_name}
            >>> m.action_log_message('I10004', last_name='Taro', first_name='Tanaka')
            '名前は Taro Tanaka. Tanaka Taro'

            >>> # I10003,{}第一引数[{param1}]/第二引数[{param2}]を見直してください。
            >>> m.action_log_message('I10003', '引数チェックエラー。', param1='1', param2='2')
            '引数チェックエラー。第一引数[1]/第二引数[2]を見直してください。'

        """
        message = cls.search_message(message_id)
        if len(args) > 0 and len(kwargs) > 0:
            message = message.format(*args, **kwargs)
        elif len(args) > 0:
            message = message.format(*args)
        elif len(kwargs) > 0:
            message = message.format(**kwargs)

        return message


if __name__ == '__main__':
    import doctest
    doctest.testmod()

common/init.py

from common.message.message import MessageNotFoundError
from common.message.message import Message as m

tools/test.py

import logging
from common import m

formatter = '%(asctime)s %(processName)s %(threadName)s %(message)s'
logging.basicConfig(level=logging.DEBUG, format=formatter)

# D10001,{}処理-START
logging.debug(m.action_log_message('I10001', '○○'))
>>> 2019-09-14 00:59:25,559 MainProcess MainThread ○○処理-START

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1