Skip to content

Instantly share code, notes, and snippets.

@szapp
Last active March 25, 2026 15:34
Show Gist options
  • Select an option

  • Save szapp/9b895c8d12eac63e29679f1e52a33aed to your computer and use it in GitHub Desktop.

Select an option

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.
#!/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