import logging
class LogLevelContext:
def __init__(self, logger, level):
self.logger = logger
self.level = level
self.original_level = logger.level
def __enter__(self):
self.logger.setLevel(self.level)
def __exit__(self, exc_type, exc_val, exc_tb):
self.logger.setLevel(self.original_level)
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
with LogLevelContext(logger, logging.DEBUG):
logger.debug("Это отладочное сообщение, видимое только внутри контекста.")
logger.info("Это информационное сообщение.")
logger.info("Это информационное сообщение, уровень логирования восстановлен.")
В `__enter__` мы меняем уровень логирования, а в `__exit__` возвращаем его обратно.
Контекстные менеджеры позволяют временно изменять состояние какого-либо ресурса (в данном случае, уровень логирования) внутри блока with
, а затем автоматически восстанавливать исходное состояние после выхода из этого блока. Это удобно для временной отладки или выполнения специфических операций, требующих определенного уровня логирования.
Вот пример реализации контекстного менеджера для временного изменения уровня логирования:
import logging
class LoggingLevelContext:
def __init__(self, logger, level):
self.logger = logger
self.level = level
self.original_level = logger.level # Store the original level
def __enter__(self):
self.logger.setLevel(self.level)
return self.logger
def __exit__(self, exc_type, exc_val, exc_tb):
self.logger.setLevel(self.original_level) # Restore the original level
Объяснение кода:
__init__(self, logger, level)
: Конструктор, принимает экземпляр логгера и новый уровень логирования. Сохраняет исходный уровень логгера в self.original_level
.__enter__(self)
: Вызывается при входе в блок with
. Устанавливает новый уровень логирования для указанного логгера. Возвращает экземпляр логгера (необязательно, но удобно для дальнейшего использования внутри блока with
).__exit__(self, exc_type, exc_val, exc_tb)
: Вызывается при выходе из блока with
(независимо от того, было ли исключение). Восстанавливает исходный уровень логирования, сохраненный в self.original_level
. Параметры exc_type
, exc_val
и exc_tb
содержат информацию об исключении, если оно произошло, но в данном случае они не используются.Пример использования:
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO) # Set a default logging level
# Add a handler to the logger (e.g., a StreamHandler to print to the console)
handler = logging.StreamHandler()
logger.addHandler(handler)
logger.info("This message will be logged at the INFO level.")
logger.debug("This message will NOT be logged because the logger's level is INFO.")
with LoggingLevelContext(logger, logging.DEBUG):
logger.debug("This message WILL be logged because the level is temporarily DEBUG.")
logger.info("This message will ALSO be logged because DEBUG is lower than INFO.")
logger.info("This message will be logged again at the INFO level.")
logger.debug("This message will NOT be logged because the logger's level is back to INFO.")
Альтернативный подход (использование logging.disable
):
Хотя logging.disable
не является контекстным менеджером в чистом виде, его также можно использовать для временного отключения логирования. Однако, он отключает логирование глобально, а не для конкретного логгера. Поэтому, использование контекстного менеджера, как показано выше, обычно предпочтительнее, особенно если у вас несколько логгеров.
import logging
class DisableLoggingContext:
def __init__(self, disable_level=logging.CRITICAL + 1): # Default: disable everything
self.disable_level = disable_level
self.previous_disable = logging.disable
def __enter__(self):
self.previous_disable = logging.disable
logging.disable(self.disable_level)
def __exit__(self, exc_type, exc_val, exc_tb):
logging.disable(self.previous_disable)
Пример использования DisableLoggingContext
:
import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
logger.addHandler(handler)
logger.info("This message will be logged.")
with DisableLoggingContext(logging.ERROR): # Disable logging of INFO, WARNING, DEBUG
logger.info("This message will NOT be logged.")
logger.error("This message WILL be logged because logging.ERROR is not disabled.")
logger.info("This message will be logged again.")
В заключение, контекстные менеджеры предоставляют элегантный и безопасный способ временного изменения уровня логирования, обеспечивая автоматическое восстановление исходного состояния после завершения блока with
.