Disclaimer: This is my first article. I will try to post once in a while if I think any article might help someone.
Personally, I hate buzzwords so I will try to keep it simple. Suggestions are welcome.
Writing logs for your program is one of the most crucial thing in software development. It helps to find bugs, write analytics, keep a track of traffic, verify if there is any DDoS attack in your server, etc.
Personally, as a person who never had a mentor and learned myself to code, I have always struggled how to maintain a clean code in my projects. So, in order to avoid writing many
try... catch... clauses in every function I though if I write a decorator where I catch the error and log it in a
UPDATE: There is a typo in the flowchart. It should be Throw Exception. My apologies.
First we create a file named
log.py (or whatever name you want). Here we will write the log decorator.
import logging import functools def _generate_log(path): """ Create a logger object :param path: Path of the log file. :return: Logger object. """ # Create a logger and set the level. logger = logging.getLogger('LogError') logger.setLevel(logging.ERROR) # Create file handler, log format and add the format to file handler file_handler = logging.FileHandler(path) # See https://docs.python.org/3/library/logging.html#logrecord-attributes # for log format attributes. log_format = '%(levelname)s %(asctime)s %(message)s' formatter = logging.Formatter(log_format) file_handler.setFormatter(formatter) logger.addHandler(file_handler) return logger def log_error(path='<path>/log.error.log'): """ We create a parent function to take arguments :param path: :return: """ def error_log(func): @functools.wraps(func) def wrapper(*args, **kwargs): try: # Execute the called function, in this case `divide()`. # If it throws an error `Exception` will be called. # Otherwise it will be execute successfully. return func(*args, **kwargs) except Exception as e: logger = _generate_log(path) error_msg = 'And error has occurred at /' + func.__name__ + '\n' logger.exception(error_msg) return e # Or whatever message you want. return wrapper return error_log
Now, we create another Python file. Let's call it
divive_num.py. Here we create a function called
divide() which divides two numbers.
def divide(num1, num2): return num1 / num2 if __name__ == '__main__': result = divide(10, 0) print(result)
But when we execute this code, the error message will be shown in console and not in a log file. In order to add logging in this function we import
log.py module and call
log_error() function as a decorator.
import log @log.log_error() def divide(num1, num2): return num1 / num2 if __name__ == '__main__': result = divide(10, 0) print(result)
After we run this code, a log file will be created based on the path that you added and inside that file the error log will be appended.
ERROR 2020-02-20 14:39:56,233 And error has occurred at /divide Traceback (most recent call last): File "<path>/log.py", line 44, in wrapper return func(*args, **kwargs) File "<path>/divide_num.py", line 6, in divide return num1 / num2 ZeroDivisionError: division by zero
Now, every time we create a function, we can add
@log.log_error() decorator and all the error logs will be appended in that file.