Skip to content

stdout redirection issues #588

@henryiii

Description

@henryiii

There are several issues with the example of the DummyTqdmFile in the readme:

  1. file = None in the class makes it a class level variable, rather than object level. It should be removed or changed to __slots__ = ("file",).
  2. The catch exception line is useless, all it does is rethrow. You can leave it out safely. (finally does the job)
  3. Mentioning redirect_stdout (Python 3.4+) and redirect_stderr (Python 3.5+) in contextlib might be nice for people using those versions of Python.
  4. tdqm.write does not behave like a normal .write, it adds a \n. This causes lots of issues with this overwrite, especially inside nested progress bars. I worked on this a while, and could not get the redirect to work and produce the correct override.
  5. This would be a great utility to have in the library. You could add a parameter for the progress bar so that it could be general to notebook progress bars too (if needed)

EDIT: I forget to add file=sys.stdout, dynamic_ncols=True, that solved 4.

Here's an example of the updated example with fixes for several of the points above:

from contextlib import contextmanager, redirect_stdout, redirect_stderr
import sys

class DummyTqdmFile(object):
    """Dummy file-like that will write to tqdm"""
    __slots__ = ("file", "progress")
    
    def __init__(self, file, progress):
        self.file = file
        self.progress = progress

    def write(self, x):
        # Avoid print() second call (useless \n)
        if len(x.rstrip()) > 0:
            self.progress.write(x.strip(), file=self.file)

    def flush(self):
        return getattr(self.file, "flush", lambda: None)()

# All Python versions:
def tqdm_redirect(progress):
    orig_out_err = sys.stdout, sys.stderr
    try:
        sys.stdout = DummyTqdmFile(sys.stdout, progress)
        sys.stderr = DummyTqdmFile(sys.stderr, progress)
        yield orig_out_err[0]
    # Always restore sys.stdout/err if necessary
    finally:
        sys.stdout, sys.stderr = orig_out_err

# Python 3.5+ version:
@contextmanager
def tqdm_redirect(progress):
    orig_out = sys.stdout
    with redirect_stdout(DummyTqdmFile(sys.stdout, progress)), redirect_stderr(DummyTqdmFile(sys.stderr, progress)):
        yield orig_out

Note that the final progress bar covers up the prompt if leave is not set to False.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions