How to catch exceptions using python lambdas

陌路散爱 提交于 2019-12-24 04:31:09

问题


Assuming Python version >=3 and calling a list of functions. I would like to write a lambda function that handles exceptions. Thing is, it does not work, when there is an exception thrown in a function, the program returns and the call stack is not seeing the executeFunction in it.

How to do so?

def executeFunction(x):
    try:
        x
    except:
        print('Exception caught')


executeFunction(func1())
executeFunction(func2())
executeFunction(func3())
executeFunction(func4())
executeFunction(func5())
executeFunction(func6())

回答1:


executeFunction won't be called if the exception is raised by any of the function calls, that is, while the argument is still being evaluated.

You should consider passing the callable instead and calling it inside the try/except clause:

def executeFunction(x):
    try:
        x()
    except SomeException:
        print('Exception caught')

executeFunction(func1)

Any errors raised from x() are now handled by the enclosing try/except clause.

For functions with arguments you can use functools.partial (or a lambda) to defer the call using the arguments:

from functools import partial

def executeFunction(x):
    try:
        x()
    except SomeException:
        print('Exception caught')

executeFunction(partial(func1, arg1, argn))
# executeFunction(lambda: func1(arg1, argn))

You could also exploit Python's decorator syntax to use calls to the functions themselves directly without having to explicitly call executeFunction directly, giving much cleaner code from the caller's side:

def executeFunction(func):
    def wrapper(*args, **kwargs):
        try:
            func(*args, **kwargs)
        except SomeException:
            print('Exception caught')
    return wrapper

@executeFunction
def func1(arg1, arg2):
    ...
@executeFunction
def func2(arg1):
    ...


func1(arg1, arg2) # -> executeFunction(func1)(arg1, arg2)
func2(arg1)       # -> executeFunction(func2)(arg1)



回答2:


The short answer is that you can not really handle exceptions inside within an expression.

A longer answer would be: you may achieve what you want by using some contrived tricks. Of course you should not do that for serious purposes, but what you can actually do inside an expression is:

  • define "on the fly" new expressions by using tricky combinations of type() and of setattr(), like this:

    MyException = (lambda o:
                      setattr(o, '__init__',
                          lambda self: setattr(self,"test", 42))
                   or setattr(o, 'my_funny_method', lambda self:True)
                   or setattr(o, 'my_other_funny_method', lambda self:False)
                   or o)(type("MyException", (BaseException,), {}))
    e = MyException()
    print(type(e), "with attribute test =", e.test)
    print(e.my_funny_method())
    raise e
    
  • raise any exception; not only by performing ad hoc operations but also in a more general manner if required:

    (_ for _ in ()).throw(ZeroDivisionError("Hello World"))
    
  • catch some exceptions by tricky uses of ad hoc features like the way StopIteration is handled by iterators:

    is_odd = lambda n: ((lambda l:
        (l and l.pop()) or "An exception was caught")
          (list((lambda: (yield from (n if n%2
             else (_ for _ in ()).throw(StopIteration) for _ in (None,))))())))
    print(is_odd(5))
    print(is_odd(8))
    

You can read more about it at http://baruchel.github.io/python/2018/06/20/python-exceptions-in-lambda/ .



来源:https://stackoverflow.com/questions/45803245/how-to-catch-exceptions-using-python-lambdas

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!