Irene Ferfoglia
Irene Ferfoglia

Reputation: 67

How can I insert a 'with' statement under a condition?

I have a piece of code structured this way:

try:
    from tqdm import tqdm
    use_tqdm = True
except ImportError:
    use_tqdm = False


if use_tqdm:
    with tqdm(total=5) as pbar:
        # --- many nested for loops ---
        pbar.update(1)
else:
    # --- identical nested for loops, without pbar.update(1) ---

How can I avoid repeating said long block of code?

I cannot put the condition only on the single pbar line inside because what tqdm does is create a progress bar, so it needs to be instantiated only once.

I think I'm looking for a way to tell Python "hey, consider the with statement only if use_tqdm = True, otherwise pretend it never existed", but any other suggestions are very welcome.

Thanks!

(tqdm package: https://github.com/tqdm/tqdm )

Upvotes: 0

Views: 191

Answers (3)

chepner
chepner

Reputation: 531718

try:
    from tqdm import tqdm
except ImportError:
    class tqdm:
        def __int__(self, *args, **kwargs):
            pass

        def __enter__(self):
            class Dummy:
                def update(self, *args, **kwargs):
                    pass

            return Dummy()

        def __exit__(self, *args):
            pass

with tqdm(total = 5) as pbar:
   --- many nested for loops ---
            pbar.update(1)

If the import fails, you just get a dummy context and an object whose update method is a no-op. No separate code is needed.

Upvotes: 1

Rainfall
Rainfall

Reputation: 93

You can create a function for that nested for loops with input of pbar. Inside that function, you check if the pbar passed in is None meaning not to update progress bar, otherwise use it and call update:

try:
    from tqdm import tqdm
    use_tqdm = True
except ImportError:
    use_tqdm = False

def process_nested_for_loops(pbar):
    # --- many nested for loops ---
        if pbar is not None:
            pbar.update(1)


if use_tqdm = True:
   with tqdm(total = 5) as pbar:
       process_nested_for_loops(pbar)
else:
   process_nested_for_loops(None)

Upvotes: 0

Poohl
Poohl

Reputation: 1924

So there's two separate problems here:

  • replicated but very similar code
  • conditional allocation of resources

For the first one define a function that optionally takes a pbar and defaults to something that signals "ignore me". As @Michael-Butscher suggested either create a dummy class that just has a pass in all functions you wish to ignore or, a bit more dirty, just guard ever occurrence with an if. Example:

class PbarDummy:
    def update(self, _):
        pass

def many_for_loops(pbar=PbarDummy()):
   --- many nested for loops ---
      pbar.update(1)

This then also solves your second problem, as you can conditionally call the function inside the with block or not.

if use_tqdm:
   with tqdm(total = 5) as pbar:
      many_for_loops(pbar=pbar)
else:
   many_for_loops()

Upvotes: 0

Related Questions