fastai / fastprogress

Simple and flexible progress bar for Jupyter Notebook and console
Apache License 2.0
1.08k stars 105 forks source link

Question: Hook to replace ConsoleProgressBar print statements #11

Closed devforfu closed 5 years ago

devforfu commented 5 years ago

It is not an issue per se, however, I wonder is it possible to modify ConsoleProgressBar class a bit to make possible to replace print calls with something like self.write, and allow to insert your own writer?

I know that Python allows you to redirect stdin with a special context manager but it would be more suitable for one to use custom output method. Because, for example, if you're using logging, you need to do the work twice, i.e., setup logger, and redirect stream. And if the progress bar could be configurable, then you could just pass logger instance inside or something.

I mean, something like this (shouldn't be exactly this solution, of course):

class ConsoleProgressBar(ProgressBar):
    length:int=50
    fill:str='█'

    def __init__(self, gen, total=None, display=True, leave=True,
                       parent=None, auto_update=True, writer_fn=print):

        self.max_len,self.prefix = 0,''
        super().__init__(gen, total, display, leave, parent, auto_update)
        self.write = writer_fn

    def on_iter_end(self):
        if not self.leave and printing():
            self.write(f'\r{self.prefix}' + ' ' * (self.max_len - len(f'\r{self.prefix}')), end = '\r')

    def on_update(self, val, text):
        if self.display:
            filled_len = int(self.length * val // self.total)
            bar = self.fill * filled_len + '-' * (self.length - filled_len)
            to_write = f'\r{self.prefix} |{bar}| {text}'
            if len(to_write) > self.max_len: self.max_len=len(to_write)
            if printing(): self.write(to_write, end = '\r')
sgugger commented 5 years ago

Starting v1.0.15, you have a global WRITE_FN you can change (default print). Just type:

import fast_progress
fast_progress.fast_progress.WRITER_FN = {your func}

Let me know if this doesn't work.

attibalazs commented 4 years ago

this was my solution to this, thanks for the comment above this builds on that

it prints if the text needs to be overwritten and logs to file if its not an update to the progress bar.

import fastprogress

def log_fastai_msg(to_write, end=None):
    """log progress message from fastai"""
    if end:
        print(to_write, end=end)
    else:
        logging.info(to_write)
        print(to_write)

# set fastprogress to write to log file
fastprogress.fastprogress.WRITER_FN = log_fastai_msg