【问题标题】:python log exceptions decorator for non stable functions用于非稳定函数的 python 日志异常装饰器
【发布时间】:2013-04-10 17:24:00
【问题描述】:

我想在问题函数中记录异常(可变页面的 html 解析),所以我认为最好的解决方案是使用某种装饰器将异常记录到文件中,包括时间、异常类型、代码中的异常行和函数调用参数,例如:

@exception_catch(log_path='example.log')
def example(x,y):
    raise Exception('123')

解决此类任务的最佳实践是什么,或者可能是好的 Python 库?

【问题讨论】:

    标签: python logging decorator


    【解决方案1】:

    您可能希望按照 unutbu 的建议进行操作,因为它更灵活,最终也同样简单。但是,如果您对 logging 的额外细节感到不知所措,请按照您的要求执行以下操作:

    def exception_catch(log_path):
        def deco(func):
            @functools.wraps(func)
            def wrapper(*args, **kwargs):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    with open(log_path, 'a') as log:
                        log.write('{} {} {} {} {}\n'.format(datetime.datetime.now(), 
                                                            type(e), e, args, kwargs))
                    # This will return None on error, of course
            return wrapper
        return deco
    

    当然,您可以将任何您想要的内容放入format,包括来自上述任何作用域的任何局部变量。您要求的唯一棘手的一点是“代码中的异常行”。 2.x 与 3.x 的详细信息略有不同(请参阅traceback 模块了解您需要了解的大部分内容),但这里有一个 3.x 示例,可以准确地为您提供所需的内容:

    except Exception as e:
        filename, line, func, text = traceback.extract_stack(limit=1)[0]
        with open(log_path, 'a') as log:
            log.write('time: {} type: {} line: {} args: {}\n'.format(
                datetime.datetime.now(), 
                type(e),
                line,
                args))    
    

    【讨论】:

      【解决方案2】:

      不是传递文件的路径,而是传递一个记录器。这样,装饰器的用户可以决定是否要登录到文件或控制台,或其他任何东西。记录器还将确定记录消息的格式。

      您可能还需要一个exception 参数来定义您想要捕获的异常类型。 (下面,exception 可以采用 ExceptionExceptions 的元组。


      import logging
      
      def catch_exception(exception=Exception, logger=logging.getLogger(__name__)):
          def deco(func):
              def wrapper(*args, **kwargs):
                  try:
                      result = func(*args, **kwargs)
                  except exception as err:
                      logger.exception(err)
                  else:
                      return result
              return wrapper
          return deco
      
      @catch_exception()
      def example(x,y):
          raise Exception('123')
      
      logging.basicConfig(filename='/tmp/error.log', level=logging.DEBUG,
                          datefmt='%Y-%m-%d %H:%M:%S',
                          format='%(asctime)s %(module)s %(levelname)s: %(message)s')
      
      example(1,2)
      

      【讨论】:

      • +1。但是为什么你有else 块? return result 无法筹集任何额外的资金。
      猜你喜欢
      • 2011-10-30
      • 2016-12-14
      • 1970-01-01
      • 2023-03-17
      • 2010-12-11
      • 2021-04-27
      • 2015-12-01
      • 2014-07-21
      • 2019-04-13
      相关资源
      最近更新 更多