[Python] Redirect print command in python script through tqdm.write()

Discussão em 'Python' iniciado por Stack, Agosto 11, 2025.

  1. Stack

    Stack Membro Participativo

    I'm using tqdm in Python to display console-progressbars in our scripts. However, I have to call functions which print messages to the console as well and which I can't change. In general, writing to the console while displaying progress bars in the console messes up the display like so:

    from time import sleep
    from tqdm import tqdm

    def blabla():
    print "Foo blabla"

    for k in tqdm(range(3)):
    blabla()
    sleep(.5)


    This creates the output:

    0%| | 0/3 [00:00<?, ?it/s]Foo
    blabla
    33%|###########6 | 1/3 [00:00<00:01, 2.00it/s]Foo
    blabla
    67%|#######################3 | 2/3 [00:01<00:00, 2.00it/s]Foo
    blabla
    100%|###################################| 3/3 [00:01<00:00, 2.00it/s]


    According to the documentation of tqdm the method tqdm.write() provides a means to write messages to the console without breaking the displayed progressbars. Thus, the right output is provided by this snippet:

    from time import sleep
    from tqdm import tqdm

    def blabla():
    tqdm.write("Foo blabla")

    for k in tqdm(range(3)):
    blabla()
    sleep(.5)


    And looks like this:

    Foo blabla
    Foo blabla
    Foo blabla
    100%|###################################| 3/3 [00:01<00:00, 1.99it/s]


    On the other hand, there is this solution which permits to silence those functions by quite elegantly redirecting sys.stdout into the void. This works perfectly well for silencing the functions.

    Since I want to display the messages from these functions nonetheless without breaking the progress bars, I tried to merge both solutions into one by redirecting sys.stdout to tqdm.write() and, in turn, letting tqdm.write() write to the old sys.stdout. This results in the snippet:

    from time import sleep

    import contextlib
    import sys

    from tqdm import tqdm

    class DummyFile(object):
    file = None
    def __init__(self, file):
    self.file = file

    def write(self, x):
    tqdm.write(x, file=self.file)

    @contextlib.contextmanager
    def nostdout():
    save_stdout = sys.stdout
    sys.stdout = DummyFile(save_stdout)
    yield
    sys.stdout = save_stdout

    def blabla():
    print "Foo blabla"

    for k in tqdm(range(3)):
    with nostdout():
    blabla()
    sleep(.5)


    However, this actually creates an even more messed up output as before:

    0%| | 0/3 [00:00<?, ?it/s]Foo
    blabla


    33%|###########6 | 1/3 [00:00<00:01, 2.00it/s]Foo
    blabla


    67%|#######################3 | 2/3 [00:01<00:00, 2.00it/s]Foo
    blabla


    100%|###################################| 3/3 [00:01<00:00, 2.00it/s]


    FYI: calling tqdm.write(..., end="") inside DummyFile.write() creates the same result as the first output which is still messed up.

    I can't understand why this wouldn't work, since tqdm.write() is supposed to manage clearing the progress bar before writing the message and then rewriting the progress bar.

    What am I missing?

    Continue reading...

Compartilhe esta Página