2013-04-17 2 views
1

Я хочу регистрировать исключение в проблемных функциях (html-синтаксический анализ изменяемых страниц), поэтому я считаю лучшим решением здесь какой-то декоратор, который записывает исключение в файл, со временем, типом исключения, строка исключения в коде и вызов функции аргументов, некоторые вещи, как:python log exceptions decorator для нестабильных функций

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

Что является лучшей практикой для решения такого рода задач или может быть хорошим питон ЛИЭСОМ для этого?

ответ

2

Вы, вероятно, хотите сделать, как 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 vs. 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 может принимать 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) 
+0

+1. Но почему у вас есть блок 'else'? Нет никакого способа вернуть результат. – abarnert

Смежные вопросы