将“print”功能更改为“tqdm.write”,以便日志记录不会干扰进度条

时间:2016-07-23 15:40:49

标签: python logging tqdm

我有一个简单的问题:如何将内置Python记录器的print函数更改为tqdm.write,以便日志消息不会干扰tqdm的进度条?谢谢!

5 个答案:

答案 0 :(得分:17)

您需要一个自定义日志记录处理程序:

import logging
import tqdm

class TqdmLoggingHandler(logging.Handler):
    def __init__(self, level=logging.NOTSET):
        super().__init__(level)

    def emit(self, record):
        try:
            msg = self.format(record)
            tqdm.tqdm.write(msg)
            self.flush()
        except (KeyboardInterrupt, SystemExit):
            raise
        except:
            self.handleError(record)  

然后将其添加到日志链:

import time

log = logging.getLogger (__name__)
log.setLevel (logging.INFO)
log.addHandler (TqdmLoggingHandler ())
for i in tqdm.tqdm (range (100)):
    if i == 50:
        log.info ("Half-way there!")
    time.sleep (0.1)

编辑:修复了对超级TqdmLoggingHandler的init方法的调用中的错误,这是由努力的读者@BlaineRogers在评论中指出的。 (如果有人想进一步阅读有关Python这个阴暗区域的内容,我建议https://fuhm.net/super-harmful/

答案 1 :(得分:2)

最简单的方法是更改​​ StreamHandler 对象的流,例如:

import logging
from tqdm import tqdm, trange
import time

log = logging.getLogger(__name__)
log.setLevel(logging.INFO)
handler = logging.StreamHandler()
handler.setStream(tqdm) # <-- important
handler = log.addHandler(handler)

for i in trange(100):
    if i == 50:
        log.info("Half-way there!")
    time.sleep(0.1)

答案 2 :(得分:1)

一个不那么优雅的简单解决方案是将tqdm对象转换为字符串。之后,您可以记录该消息(或根据需要进行处理)。 “ format_dict”属性也可能有用:

Option::<T>::None

输出:

from tqdm import tqdm
import time

#loop with progressbar:
it=tqdm(total=10)
for i in range(10):
    time.sleep(0.1)
    it.update(1)

it.close()
print("\n","--"*10)

# Convert tdqm object last output to sting
str_bar_msg = str(it)
print(str_bar_msg)

# See attributes:
print(it.format_dict)

最诚挚的问候

答案 3 :(得分:1)

基于上面 RolKau 的回答,简化了:

import logging
from tqdm import tqdm


class TqdmLoggingHandler(logging.StreamHandler):
    """Avoid tqdm progress bar interruption by logger's output to console"""
    # see logging.StreamHandler.eval method:
    # https://github.com/python/cpython/blob/d2e2534751fd675c4d5d3adc208bf4fc984da7bf/Lib/logging/__init__.py#L1082-L1091
    # and tqdm.write method:
    # https://github.com/tqdm/tqdm/blob/f86104a1f30c38e6f80bfd8fb16d5fcde1e7749f/tqdm/std.py#L614-L620

    def emit(self, record):
        try:
            msg = self.format(record)
            tqdm.write(msg, end=self.terminator)
        except RecursionError:
            raise
        except Exception:
            self.handleError(record)

测试:

import time

log = logging.getLogger(__name__)
log.setLevel(logging.INFO)
log.addHandler(TqdmLoggingHandler())
#   ^-- Assumes this will be the unique handler emitting messages to sys.stdout.
#       If other handlers output to sys.stdout (without tqdm.write),
#       progress bar will be interrupted by those outputs

for i in tqdm(range(20)):
    log.info(f"Looping {i}")
    time.sleep(0.1)

警告:如果您在 Jupyter 笔记本上工作,进度条将被中断,AFAIK 无法避免。

答案 4 :(得分:0)

TLDR:

假设您的大多数日志都以logging.info打印,请将Logger Level设置为WARN / ERROR(在PyCharm终端中进行了测试)。

这将禁止打印logging.info()

详细信息:

我用来获取主要日志记录语句和tqdm打印件的一种技术是更改Logger's level(注意:在PyCharm的终端中经过测试)。

我将代码中的大多数日志设置为logging.info()logging.debug()。因此,当我在logging level文件中将__main__设置为:

import logging
logging.getLogger().setLevel(logging.ERROR)

我的日志如下:

Plotting chunk 8 (reweighted=False)
100%|██████████| 150/150 [09:33<00:00,  3.83s/it]

否则,如果我有:

import logging
logging.getLogger().setLevel(logging.INFO)

我的日志看起来像,tqdm甚至没有显示:

Plotting chunk 8 (reweighted=False)
INFO:root:Paired 231/231 trigger results.
INFO:root:Paired 3032/3244 trigger results.
...
INFO:root:>>>>>>>>>> STAT GIF <<<<<<<<<<
  0%|          | 0/150 [00:00<?, ?it/s]INFO:root:Before adding missing triggers, #trig=3032
INFO:root:After adding missing triggers, #trig=4423032
INFO:bcr_pipeline.utils:_add_missing_background_data: 0:00:00.473584
INFO:root:Background datapoints 4423032
INFO:root:Injection datapoints 231
INFO:root:Foreground datapoints 2
INFO:bcr_pipeline.utils:get_plotting_data: 0:00:00.627285
INFO:root:FAP obtained 0.07 at x=6.8337292336858795
  1%|          | 1/150 [00:03<09:40,  3.90s/it]INFO:root:Before adding missing triggers, #trig=3032
INFO:root:After adding missing triggers, #trig=4423032
INFO:bcr_pipeline.utils:_add_missing_background_data: 0:00:00.567175
INFO:root:Background datapoints 4423032
INFO:root:Injection datapoints 231
INFO:root:Foreground datapoints 2
INFO:bcr_pipeline.utils:get_plotting_data: 0:00:00.732627
INFO:root:FAP obtained 0.07 at x=6.932632217545759
  1%|▏         | 2/150 [00:08<09:48,  3.98s/it]INFO:root:Before adding missing triggers, #trig=3032
...