Silence tqdm's output while running tests or running the code via cron

DjangoCronTqdm

Django Problem Overview


I'm using tqdm to display progress bars while some long-running Django management commands complete. It works great (so easy to use!), but...

When I run unit tests over my code, I want to stop the progress bars from outputting. And if I run those commands in the background using cron or some other means, I'd also want the progress bars not to be in the output.

I can't see an easy way to do these two things, but perhaps I've missed something?

Django Solutions


Solution 1 - Django

There is a disable argument which you can set to True to silence any tqdm output (and in fact it will totally skip the progress bar calculations too, not just the display).

To dynamically switch it, you can just add a commandline argument to your script that will define if disable is set or not. This should work for both unit testing and cron.

Solution 2 - Django

Example using the 'disable' parameter:

from tqdm import tqdm
import time

for i in tqdm(range(10), disable=True):
    time.sleep(1)

Solution 3 - Django

This is very common use case when you need to globally disable all tqdm's, desirably without changing the code in all places where it is used and which you probably do not control. Discussions about implementing such a feature last many years and lead to nothing (1, 2, 3, 4). Users need to patch tqdm in order to stop polluting logs. One of the shortest ways I found is probably this:

from tqdm import tqdm
from functools import partialmethod

tqdm.__init__ = partialmethod(tqdm.__init__, disable=True)

The idea is defaulting the already supported (but not sufficient) parameter of the initializer. It is not sufficient because you need to add it in each place where tqdm is instantiated, which you don't want, that's why we modify __init__ to make such a default.

The patch works independently of the order of imports and will affect all subsequently created tqdm objects.

Solution 4 - Django

Use mock.patch to replace tqdm in the code that's using it with something like this:

def notqdm(iterable, *args, **kwargs):
    """
    replacement for tqdm that just passes back the iterable
    useful to silence `tqdm` in tests
    """
    return iterable

and in the test:

import mock

...

    @mock.patch('tested_code_module.tqdm', notqdm)
    def test_method(self):
    ...

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPhil GyfordView Question on Stackoverflow
Solution 1 - DjangogaborousView Answer on Stackoverflow
Solution 2 - DjangocanninView Answer on Stackoverflow
Solution 3 - DjangogreatvovanView Answer on Stackoverflow
Solution 4 - Djangoshade of blueView Answer on Stackoverflow