0
0

PythonでFile名-関数名-引数をログに出したい

Last updated at Posted at 2024-09-08

Pythonで関数ごとにログを出したいが関数名とか毎回手入力は面倒くさいなあという方用

要らないログを省いた結果、コード自体が長くなってしまったので、モジュール化することにした。
自分を呼び出してしまうので、ファイル名を変更する方は__file__で自動化すればいいかもしれない

必要であればloggingで出力する

ログ出力用

getLog.py

import inspect
from datetime import datetime
import os
import functools

def log_function_call(func):
    """関数が呼び出されるたびにログを出力するデコレータ"""
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        # 呼び出し元のフレームを取得
        frame = inspect.currentframe()

        # フレームスタックを辿り、`getLog.py` 以外のフレームを探す
        for outer_frame in inspect.getouterframes(frame):
            file_name = os.path.basename(outer_frame.filename)
            # `getLog.py` 以外のファイルを探す 呼び出し元になってしまうため
            if "getLog.py" not in file_name and not file_name.startswith(("pydevd", "debugpy")):
                break

        current_function = func.__name__
        line_number = outer_frame.lineno
        timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')

        # 引数の情報を取得
        args_str = ', '.join(repr(arg) for arg in args)
        kwargs_str = ', '.join(f"{key}={value!r}" for key, value in kwargs.items())
        all_args_str = ', '.join(filter(None, [args_str, kwargs_str]))

        # 引数がない場合も () を表示
        if all_args_str:
            args_display = f"({all_args_str})"
        else:
            args_display = "()"

        # ログ出力
        print(f"{timestamp} - {file_name}:{line_number} - {current_function}{args_display}")

        # 元の関数を実行
        return func(*args, **kwargs)

    return wrapper

実装用コード

from getLog import log_function_call

@log_function_call
def test(a):
    print(f"tggest: {a}")

@log_function_call
def example_function(x, y, z=1):
    print("example_function:x, y, z=0")
if __name__ == "__main__":
    test("Hello")
    example_function(5, 10, z=3)
    example_function(1, 2)  # 引数なし

結果

2024-09-08 12:59:38 - main.py:11 - test('Hello')
tggest: Hello
2024-09-08 12:59:38 - main.py:12 - example_function(5, 10, z=3)
example_function:x, y, z=0
2024-09-08 12:59:38 - main.py:13 - example_function(1, 2)
example_function:x, y, z=0
0
0
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
0