Last active
March 25, 2026 15:34
-
-
Save szapp/9b895c8d12eac63e29679f1e52a33aed to your computer and use it in GitHub Desktop.
The progress bar package tqdm for Python offers an incomplete `logging_redirect_tqdm`, see countless unresolved Github issues at https://github.com/tqdm/tqdm/issues?q=is%3Aopen%20is%3Aissue%20logging. Instead one can use this class that inherits from `logging.StreamHandler` to achieve it directly.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env -S uv run --script | |
| # /// script | |
| # requires-python = ">=3.10" | |
| # dependencies = [ | |
| # "tqdm", | |
| # ] | |
| # /// | |
| import logging | |
| import logging.config | |
| from typing import IO | |
| from tqdm.std import tqdm as std_tqdm | |
| class TqdmStreamHandler(logging.StreamHandler): | |
| """Handler inheriting from StreamHandler to route logging stream through tqdm.""" | |
| def __init__( | |
| self, | |
| stream: IO[str] | None = None, | |
| tqdm_class: type[std_tqdm] = std_tqdm, | |
| ): | |
| super().__init__(stream=stream) | |
| self.tqdm_class = tqdm_class | |
| def emit(self, record: logging.LogRecord): | |
| try: | |
| msg = self.format(record) | |
| self.tqdm_class.write(msg, end=self.terminator, file=self.stream) | |
| self.flush() | |
| except (KeyboardInterrupt, SystemExit): | |
| raise | |
| except Exception: | |
| self.handleError(record) | |
| # Example | |
| config = { | |
| "version": 1, | |
| "disable_existing_loggers": False, | |
| "formatters": { | |
| "simple": {"format": "[%(asctime)s][%(name)s][%(levelname)s] - %(message)s"}, | |
| }, | |
| "handlers": { | |
| "console": { | |
| "()": TqdmStreamHandler, # Replaces logging.StreamHandler | |
| "formatter": "simple", | |
| "stream": "ext://sys.stdout", | |
| }, | |
| }, | |
| "root": { | |
| "handlers": ["console"], | |
| "level": "INFO", | |
| }, | |
| } | |
| logging.config.dictConfig(config) | |
| logger = logging.getLogger(__name__) | |
| for i in std_tqdm(range(1, 5)): | |
| from time import sleep | |
| sleep(0.2) | |
| logger.info("Hello World") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment