【问题标题】:How to catch exceptions using python lambdas如何使用 python lambdas 捕获异常
【发布时间】:2018-01-29 21:22:37
【问题描述】:

假设 Python 版本 >=3 并调用函数列表。 我想写一个处理异常的 lambda 函数。 问题是,它不起作用,当函数中抛出异常时,程序返回并且调用堆栈没有看到其中的executeFunction

怎么做?

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


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

【问题讨论】:

    标签: python exception lambda try-catch


    【解决方案1】:

    简短的回答是,您无法真正处理表达式内部的异常。

    更长的答案是:您可以通过一些人为的技巧来实现您想要的。当然,您不应该出于严肃的目的这样做,但是您实际上可以在表达式中执行以下操作:

    • 通过使用 type()setattr() 的巧妙组合来定义“动态”新异常,如下所示:

        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
      
    • 引发任何异常;不仅通过执行 ad hoc 操作,还可以在需要时以更一般的方式:

        (_ for _ in ()).throw(ZeroDivisionError("Hello World"))
      
    • 通过像 StopIteration 由迭代器处理的方式那样巧妙地使用 ad hoc 功能来捕获 一些 异常:

        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))
      

    您可以在http://baruchel.github.io/python/2018/06/20/python-exceptions-in-lambda/ 阅读更多相关信息。

    【讨论】:

      【解决方案2】:

      executeFunction 不会在任何函数调用引发异常时被调用,也就是说,当参数仍在被评估时。

      您应该考虑改为传递 callable 并在 try/except 子句中调用它:

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

      x() 引发的任何错误现在都由封闭的try/except 子句处理。

      对于带参数的函数,您可以使用functools.partial(或lambda)来延迟使用参数的调用:

      from functools import partial
      
      def executeFunction(x):
          try:
              x()
          except SomeException:
              print('Exception caught')
      
      executeFunction(partial(func1, arg1, argn))
      # executeFunction(lambda: func1(arg1, argn))
      

      您还可以利用 Python 的装饰器语法直接调用函数本身,而无需显式直接调用 executeFunction,从而从调用方提供更简洁的代码:

      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)
      

      【讨论】:

      • 对于带参数的函数,有没有办法将其添加得比 : def executeFunction(x, arg1="", arg2=""): if arg1 != "" and arg2 != " ": x(arg1, arg2) elif arg1 != "": x(arg1) else: x() except: print('Exception Caught in ' + x.__name__)
      • 感谢完美!
      • 我尝试使用包装器,但它仍然让我:TypeError: 'NoneType' object is not callable def executeFunction(func): def wrapper(*args, **kwargs): try: func(* args, **kwargs) except: print('Exception catched') at executeFunction def func1(arg1, arg2): print('hello') at executeFunction def func2(arg1): print('hello') 不得不改变@ with在此处@Moses Koledoye 发表评论
      • @Rems 需要返回包装器。更新:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-27
      • 1970-01-01
      • 2016-12-13
      • 2017-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多