Skip to content

Commit

Permalink
added logging_tqdm
Browse files Browse the repository at this point in the history
fixed comma in type hint

added logging_tqdm

added documentation to class

added documentation to README

python 2

flake8

also test with default logger

isort

fixed readme title underline too short
  • Loading branch information
de-code committed May 29, 2021
1 parent 05ad200 commit ba3ce3b
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 2 deletions.
19 changes: 19 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1348,6 +1348,25 @@ Helper methods are available in ``tqdm.contrib.logging``. For example:
LOG.info("console logging redirected to `tqdm.write()`")
# logging restored
Outputting progress to ``logging``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

To output the tqdm progress bar to ``logging``,
``logging_tqdm`` from the ``tqdm.contrib.logging`` may be used. For example:

.. code:: python
import logging
from time import sleep
from tqdm.contrib.logging import logging_tqdm
LOG = logging.getLogger(__name__)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
with logging_tqdm(range(10)):
sleep(0.3)
Monitoring thread, intervals and miniters
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
36 changes: 35 additions & 1 deletion tests/tests_contrib_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@
import sys
from io import StringIO

try:
from typing import Optional # pylint: disable=unused-import
except ImportError:
pass

import pytest

from tqdm import tqdm
from tqdm.contrib.logging import LOGGER as DEFAULT_LOGGER
from tqdm.contrib.logging import _get_first_found_console_logging_formatter
from tqdm.contrib.logging import _TqdmLoggingHandler as TqdmLoggingHandler
from tqdm.contrib.logging import logging_redirect_tqdm, tqdm_logging_redirect
from tqdm.contrib.logging import (
logging_redirect_tqdm, logging_tqdm, tqdm_logging_redirect)

from .tests_tqdm import importorskip

Expand Down Expand Up @@ -179,3 +186,30 @@ def test_use_root_logger_by_default_and_write_to_custom_tqdm(self):
assert isinstance(pbar, CustomTqdm)
logger.info('test')
assert CustomTqdm.messages == ['test']


class TestLoggingTqdm:
@pytest.mark.parametrize(
"logger_param,expected_logger",
[
(None, DEFAULT_LOGGER),
(LOGGER, LOGGER)
]
)
def test_should_log_tqdm_output(
self,
logger_param, # type: Optional[logging.Logger]
expected_logger # type: logging.Logger
):
try:
previous_handlers = expected_logger.handlers
out = StringIO()
stream_handler = logging.StreamHandler(out)
expected_logger.addHandler(stream_handler)
with logging_tqdm(total=2, logger=logger_param, mininterval=0) as pbar:
pbar.update(1)
finally:
expected_logger.handlers = previous_handlers
last_log_line = out.getvalue().splitlines()[-1]
assert '50%' in last_log_line
assert '1/2' in last_log_line
69 changes: 68 additions & 1 deletion tqdm/contrib/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

from ..std import tqdm as std_tqdm

LOGGER = logging.getLogger(__name__)


class _TqdmLoggingHandler(logging.StreamHandler):
def __init__(
Expand Down Expand Up @@ -47,7 +49,7 @@ def _get_first_found_console_logging_formatter(handlers):

@contextmanager
def logging_redirect_tqdm(
loggers=None, # type: Optional[List[logging.Logger]],
loggers=None, # type: Optional[List[logging.Logger]]
tqdm_class=std_tqdm # type: Type[std_tqdm]
):
# type: (...) -> Iterator[None]
Expand Down Expand Up @@ -124,3 +126,68 @@ def tqdm_logging_redirect(
with tqdm_class(*args, **tqdm_kwargs) as pbar:
with logging_redirect_tqdm(loggers=loggers, tqdm_class=tqdm_class):
yield pbar


class logging_tqdm(std_tqdm):
"""
A version of tqdm that outputs the progress bar
to Python logging instead of the console.
The progress will be logged with the info level.
Parameters
----------
logger : logging.Logger, optional
Which logger to output to (default: logger.getLogger('tqdm.contrib.logging')).
All other parameters are passed on to regular tqdm,
with the following changed default:
mininterval: 1
bar_format: '{desc}{percentage:3.0f}%{r_bar}'
desc: 'progress: '
Example
-------
```python
import logging
from time import sleep
from tqdm.contrib.logging import logging_tqdm
LOG = logging.getLogger(__name__)
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
with logging_tqdm(range(10)):
sleep(0.3)
# logging restored
```
"""
def __init__(
self,
*args,
# logger=None, # type: logging.Logger
# mininterval=1, # type: float
# bar_format='{desc}{percentage:3.0f}%{r_bar}', # type: str
# desc='progress: ', # type: str
**kwargs):
tqdm_kwargs = kwargs.copy()
self._logger = tqdm_kwargs.pop('logger', None)
tqdm_kwargs.setdefault('mininterval', 1)
tqdm_kwargs.setdefault('bar_format', '{desc}{percentage:3.0f}%{r_bar}')
tqdm_kwargs.setdefault('desc', 'progress: ')
super(logging_tqdm, self).__init__(self, *args, **tqdm_kwargs)

@property
def logger(self):
if self._logger is not None:
return self._logger
return LOGGER

def display(self, msg=None, pos=None):
if not self.n:
# skip progress bar before having processed anything
return
if not msg:
msg = self.__str__()
self.logger.info('%s', msg)

0 comments on commit ba3ce3b

Please sign in to comment.