tqdm/tqdm

Context manager to disable tqdm output from inside it

td-anne opened this issue · 1 comments

I have had occasion to use a library that wraps some of its internal iteration in tqdm calls. This means every time I call certain functions I get tqdm output, whether I want it or not (I am running the library with data for which the operations are fast and don't benefit from progress bars even in interactive settings). I do want progress bars in higher-level loops that do take a while in the same program, so globally disabling tqdm is not desirable.

More generally, I know that if I wrap some loop inside a function I write in tqdm, any user of that function is stuck with tqdm output. If I don't wrap it, I don't get progress bars even when I want them. In some cases I have added a use_tqdm boolean argument, but this is not a solution that scales.

I suggest a context manager:

with tqdm.suppress():
    library_function()

This should be implementable using ContextVars. It would have the benefit of allowing users to suppress some or all tqdm output when they know the code is running headless, even if tqdm's automatic detection fails for some reason. See also #1342, #619, #612, #950.

Depending when tqdm checks its environment variables, one might be able to simulate this using a context manager that manipulates os.environ.

  • I have marked all applicable categories:
    • documentation request (i.e. "X is missing from the documentation." If instead I want to ask "how to use X?" I understand StackOverflow#tqdm is more appropriate)
    • new feature request
  • I have visited the source website, and in particular
    read the known issues
  • I have searched through the issue tracker for duplicates
  • I have mentioned version numbers, operating system and
    environment, where applicable:
    import tqdm, sys
    print(tqdm.__version__, sys.version, sys.platform)
>>> import tqdm, sys
>>> print(tqdm.__version__, sys.version, sys.platform)
4.66.1 3.11.0 (main, Mar  1 2023, 18:26:19) [GCC 11.2.0] linux

Here is an example (manually implemented because I am not quite ready to dig inside tqdm):

tqdm_disabled = ContextVar("tqdm_disabled", default=False)


@contextlib.contextmanager
def disable_tqdm():
    t = tqdm_disabled.set(True)
    try:
        yield
    finally:
        tqdm_disabled.reset(t)

Then, because this is manual, every tqdm call looks like:

        with tqdm(total=len(tracks), disable=tqdm_disabled.get()) as pbar:

If the contextvar and manager came with tqdm this could be more graceful (and still overridable at call site or by environment variable).

Failing that, #1526 shows how a context manager using environment variables could work, if envwrap worked differently.