Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Exceptions Control/Flow Issue

I've been working in Python and ran into something that must be a common occurrence. I have five statements that all fall into a common pitfall of raising FooException and BarException. I want to run each of them, guarding against these exceptions but continuing to process even if an exception is raised after some handling is done. Now, I could do this like so:

try:
    foo()
except (FooException, BarException):
    pass
try:
    bar()
except (FooException, BarException):
    pass
try:
    baz()
except (FooException, BarException):
    pass
try:
    spam()
except (FooException, BarException):
    pass
try:
    eggs()
except (FooException, BarException):
    pass

but that is really verbose and in extreme violation of DRY. A rather brute-force and obvious solution is something like this:

def wish_i_had_macros_for_this(statements, exceptions, gd, ld):                
    """ execute statements inside try/except handling exceptions with gd and ld
    as global dictionary and local dictionary

    statements is a list of strings to be executed as statements
    exceptions is a list of strings that resolve to Exceptions
    gd is a globals() context dictionary
    ld is a locals() context dictionary

    a list containing None or an Exception if an exception that wasn't 
    guarded against was raised during execution of the statement for each
    statement is returned
    """
    s = """ 
try:    
    $STATEMENT
except (%s):
    pass
""" % ','.join(exceptions)                                                     
    t = string.Template(s)
    code = [t.substitute({'STATEMENT': s}) for s in statements]                   
    elist = list() 
    for c in code:
        try:
            exec c in gd, ld
            elist.append(None)
        except Exception, e:
            elist.append(e)
    return elist

With usage along the lines of:

>>> results = wish_i_had_macros_for_this(
                ['foo()','bar()','baz','spam()','eggs()'],
                ['FooException','BarException'],
                globals(),
                locals())
[None,None,None,SpamException,None]

Is there a better way?

like image 890
Brandon Adams Avatar asked Apr 02 '26 16:04

Brandon Adams


1 Answers

def execute_silently(fn, exceptions = (FooException, BarException)):
    try:
        fn()
    except Exception as e:
        if not isinstance(e, exceptions):
            raise

execute_silently(foo)
execute_silently(bar)
# ...
# or even:
for fn in (foo, bar, ...):
    execute_silently(fn)
like image 54
Cat Plus Plus Avatar answered Apr 04 '26 09:04

Cat Plus Plus