pythonpython-3.xsuppress

Is there a context that ignores multiple errors and continues execution without jumping?


with suppress(ValueError):
    while test_condition:
        biglist.remove(222) # element that doesn't exist, raises error. but we dont care abt this error.
        # LINE-A: more remove kind of calls where we are dont care abt ValueError(s) raised
        # LINE-B: ...
        # ...
        # LINE-Z: ...

# LINE-1: some statement..
# some more statements...

With contextlib.suppress, the while loop is stopped on the first exception that occurs and execution jumps to LINE-1. Is there an alternative construct or facility in Python where we can ignore multiple errors that happen within a context and continue execution within the context from LINE-A to LINE-Z without interruption. That is, if an exception happens at LINE-A, execution continues to LINE-B instead of jumping to LINE-1.

Using multiple try-except-finally to cover each line from LINE-A to LINE-Z is not really a clean option for me, as it severely affects readability.

try:
    #LINE-A...
except ValueError:
    pass
finally:
    try:
        #LINE-B...
     except ValueError:
        pass
     finally:
        #....

Wrapping each of LINE-A to LINE-Z with their own with suppress is one possibility but has less readability, so I am asking if there are alternatives that are more


Solution

  • What about this?

    def do_it(func, *args,suppress_exc=None, **kwargs):
        params = locals().copy()
        suppress_exc= suppress_exc or (ValueError,)
        try:
            func(*args, **kwargs)
            print("\nsweet  %s worked" % (params))
            return 0
        except suppress_exc as e: #pragma: no cover
            print("\nbummer %s failed" % (params))
            return e
    
    
    biglist = [200, 300, 400]
    
    while True:
    
        if not do_it(biglist.remove, 201):
            break
    
        if not do_it(biglist.pop, 6, suppress_exc=(IndexError,)):
            break
    
        if not do_it(biglist.remove, 200):
            break
    
        if not do_it(biglist.remove, 300):
            break
    
        if not do_it(biglist.remove, 400):
            break
    
    print("done:biglist:%s" % (biglist))
    

    out:

    bummer {'kwargs': {}, 'args': (201,), 'suppress_exc': None, 'func': <built-in method remove of list object at 0x106093ec8>} failed
    
    bummer {'kwargs': {}, 'args': (6,), 'suppress_exc': (<class 'IndexError'>,), 'func': <built-in method pop of list object at 0x106093ec8>} failed
    
    sweet  {'kwargs': {}, 'args': (200,), 'suppress_exc': None, 'func': <built-in method remove of list object at 0x106093ec8>} worked
    done:biglist:[300, 400]