| import logging | |
| import sys | |
| VERBOSITY = 3 | |
| # The root logger for the whole top-level package: | |
| _logger = logging.getLogger(__name__.rpartition('.')[0]) | |
| def configure_logger(logger, verbosity=VERBOSITY, *, | |
| logfile=None, | |
| maxlevel=logging.CRITICAL, | |
| ): | |
| level = max(1, # 0 disables it, so we use the next lowest. | |
| min(maxlevel, | |
| maxlevel - verbosity * 10)) | |
| logger.setLevel(level) | |
| #logger.propagate = False | |
| if not logger.handlers: | |
| if logfile: | |
| handler = logging.FileHandler(logfile) | |
| else: | |
| handler = logging.StreamHandler(sys.stdout) | |
| handler.setLevel(level) | |
| #handler.setFormatter(logging.Formatter()) | |
| logger.addHandler(handler) | |
| # In case the provided logger is in a sub-package... | |
| if logger is not _logger: | |
| configure_logger( | |
| _logger, | |
| verbosity, | |
| logfile=logfile, | |
| maxlevel=maxlevel, | |
| ) | |
| def hide_emit_errors(): | |
| """Ignore errors while emitting log entries. | |
| Rather than printing a message describing the error, we show nothing. | |
| """ | |
| # For now we simply ignore all exceptions. If we wanted to ignore | |
| # specific ones (e.g. BrokenPipeError) then we would need to use | |
| # a Handler subclass with a custom handleError() method. | |
| orig = logging.raiseExceptions | |
| logging.raiseExceptions = False | |
| def restore(): | |
| logging.raiseExceptions = orig | |
| return restore | |
| class Printer: | |
| def __init__(self, verbosity=VERBOSITY): | |
| self.verbosity = verbosity | |
| def info(self, *args, **kwargs): | |
| if self.verbosity < 3: | |
| return | |
| print(*args, **kwargs) |