我想在问题函数中记录异常(可变页面的 html 解析),所以我认为最好的解决方案是使用某种装饰器将异常记录到文件中,包括时间、异常类型、代码中的异常行和函数调用参数,一些像:
@exception_catch(log_path='example.log')
def example(x,y):
raise Exception('123')
解决此类任务的最佳实践是什么,或者可能是好的 Python 库?
您可能希望按照 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
,包括来自上述任何范围的任何局部变量。您要求的唯一棘手的一点是“代码中的异常行”。traceback
2.x 与 3.x 的详细信息略有不同(有关您需要了解的大部分内容,请参阅模块),但这里有一个 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))
与其传递文件的路径,不如传递一个记录器。这样,装饰器的用户可以决定是否要登录到文件或控制台,或其他任何东西。记录器还将确定记录消息的格式。
您可能还需要一个exception
参数来定义要捕获的异常类型。(下面,exception
可以Exception
采用Exceptions
.
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)