A while ago, I came up with a function that is similar to this one: Decorator to log function calls and return values, but with a different implementation.
What this function does: when applied to a function as a decorator, it captures the positional/named arguments and values passed to the function and outputs results to console (print), or to an active logger that you specify. The default behavior is to print.
The original aim was to debug code, especially unattended scripts, loops etc, and review the logs to figure out what values certain functions are actually receiving. This approach is to make it easy and convenient to monitor any function. Also, the logging feature provides a timestamp which is often relevant information when troubleshooting code.
One design goal is to have one single declaration so that the decorator can be used either with or without logger argument.
Possible improvements:
- customize the output message by way of format string or similar, for example to facilitate analysis by a log parser (eg JSON)
- there may be a better way than this implementation of
partial
that I am not sure about
The code:
debugtools.py:
from functools import wraps, partial
def show_args(func=None, logger=None):
if func is None:
return partial(show_args, logger=logger)
@wraps(func)
def wrapper(*args, **kwargs):
msg = f"{func.__name__}: (args={args}, kwargs={kwargs})"
if logger is None:
print(msg)
else:
logger(msg)
return func(*args, **kwargs)
return wrapper
main.py:
import logging
import sys
from debugtools import show_args
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)
@show_args
def my_function_with_print(*args, **kwargs):
pass
@show_args(logger=logger.debug)
def my_function_with_logging(*args, **kwargs):
pass
my_function_with_print(1, 2, 3, 4, 5, f=6, comment="Using print")
my_function_with_logging(123, comment="Using logger")
Sample output:
my_function_with_print(args=(1, 2, 3, 4, 5), kwargs={'f': 6, 'comment': 'Using print'}) 2023-05-03 22:08:58,520 - DEBUG - my_function_with_logging(args=(123,), kwargs={'comment': 'Using logger'})