python

Декораторы в Python

Dmitry Vasiliev 12:31, 2008 9 3

Последнее время заметил, что стал достаточно часто использовать в Python декораторы, благо есть синтаксическая поддержка. Раньше я уже опубликовал парочку:

В своих последних проектах я начал часто использовать декораторы для обработки ошибок. Удобно, что эту логику можно вынести в отдельное место и она не будет засорять основную логику. Плюс не надо такие обработчики писать каждый раз, а можно на самом деле переиспользовать код. Например, функция-декоратор ниже просто записывает ошибку в лог и пробрасывает ее дальше:

def error_logger(decorated):
    def decorator(*args, **kwargs):
        try:
            return decorated(*args, **kwargs)
        except:
            log.error("error in %s:", decorated.__name__, exc_info=True)
            raise
    return decorator

Один из моих последних декораторов - это декоратор для асинхронных функций обращения к базе данных с использованием Twsited. Он позволяет в случае временной ошибки попытаться повторить запрос еще несколько раз:

def retry_on_error(decorated):

    retry_timeout = 10
    retry_count = 3

    def error_handler(failure, retry_count, args, kwargs):
        retry_count -= 1
        if (retry_count >= 0
                and failure.check(adbapi.ConnectionLost, dberror.InterfaceError,
                dberror.OperationalError, dberror.InternalError)):
            log.warning(
                "error %s in %s, retry in %s seconds, %s retries remained",
                format_failure(failure), decorated.__name__,
                retry_timeout, retry_count)
            deferred = defer.Deferred()
            reactor.callLater(retry_timeout, deferred.callback, None)
            return deferred.addCallback(retry, retry_count, args, kwargs)
        return failure

    def retry(ignored, retry_count, args, kwargs):
        deferred = decorated(*args, **kwargs)
        return deferred.addErrback(error_handler, retry_count, args, kwargs)

    def decorator(*args, **kwargs):
        deferred = decorated(*args, **kwargs)
        return deferred.addErrback(error_handler, retry_count, args, kwargs)

    return decorator

Add comment

Name:
Email: (Never will be published.)
Web site:
Comment: (Paragraphs divided by empty lines, line breaks and links will be automatically formatted.)