When writing code, the key element of logging is often missed, resulting in features that go wrong while in use but cannot be traced back.
In fact, just by writing a very simple log decorator, we can greatly improve the efficiency of troubleshooting problems.
1. A rudimentary version of the decorator
Writing a decorator is very simple, because essentially a decorator is just a "higher-order" function that returns a function:
1) Functions are passed as arguments into the decorator.
2) Define a function within the decorator that handles functions passed in as arguments.
3) return the function defined within this decorator
import datetime def log(func): """ Log Decorator,Logging of simple logging functions Args: func (function): function (math.) """ def inner(*args): timestamp = str(()).split(".")[0] res = func(*args) print(f"[{timestamp}] ({func.__name__}) {args} -> {res}") return res return inner
Try using it:
@log def pluser(a, b): return a + b pluser(1, 2)
The effect is as follows:
While this achieves the functionality we need, there is actually a lot of room for optimization.
2. Ordinary version of the decorator
There was an obvious problem in the first version of the code, where the handler functions defined within the decorator did not support kwargs, and supporting kwargs in the decorator was just a matter of throwing up your hands.
The second problem is that the generation of timestamps in the form of string interception, this form is too crude. In fact, you can use strftime to do string conversion.
Modify the following:
import datetime def log(func): """ Log Decorator,Logging of simple logging functions Args: func (function): function (math.) """ def inner(*args, **kwargs): timestamp = ().strftime("%Y-%m-%d %H:%M:%S") res = func(*args, **kwargs) print(f"[{timestamp}] ({func.__name__}) {args} -> {res}") return res return inner
It seems to be pretty much optimized, but there is still room for improvement.
3. Optimized version of the decorator
In the first two versions of the code, we used print for logging output, which is actually not a standard way of handling logging.
Using the logging module to control logging output is a better option.
In order to use the logging module for logging, we need to configure the logging-related options first.
1) First, generate a logger and configure the logging level:
import logging # Get loggers, configure logging levels logger = (__name__) ('DEBUG')
2) Configure log format, add handler to control output stream:
# Default log format formatter = ("%(asctime)s - [%(levelname)s] - %(message)s") # Handler for output to console chlr = () # Configure the default log format (formatter)
Here you can set the level of logging that the handler needs to process, if you don't set it, it will default to the logger's own Level, i.e. DEBUG level.
3) Finally, add this handler to the logger:
# Add this handler to the logger (chlr)
The full configuration of logging is as follows:
import logging # Get loggers, configure logging levels logger = (__name__) ('DEBUG') # Default log format formatter = ("%(asctime)s - [%(levelname)s] - %(message)s") # Handler for output to console chlr = () # Configure the default log format (formatter) # Add this handler to the logger (chlr)
It is very simple to use, just replace print:
def log(func): """ Log Decorator,Logging of simple logging functions Args: func (function): function (math.) """ def inner(*args, **kwargs): timestamp = ().strftime("%Y-%m-%d %H:%M:%S") res = func(*args, **kwargs) (f"func: {func.__name__} {args} -> {res}") return res return inner
The effect is as follows:
In this way, a more complete log decorator is completed.
With common logging level configurations:
The above is based on Python to write a simple and practical log decorator details, more information about Python log decorator please pay attention to my other related articles!