Python Try Catch Block inside lambda Python Try Catch Block inside lambda python python

Python Try Catch Block inside lambda


Nope. A Python lambda can only be a single expression. Use a named function.

It is convenient to write a generic function for converting types:

def tryconvert(value, default, *types):    for t in types:        try:            return t(value)        except (ValueError, TypeError):            continue    return default

Then you can write your lambda:

lambda v: tryconvert(v, 0, int)

You could also write tryconvert() so it returns a function that takes the value to be converted; then you don't need the lambda:

def tryconvert(default, *types):    def convert(value):        for t in types:            try:                return t(value)            except (ValueError, TypeError):                continue        return default    # set name of conversion function to something more useful    namext = ("_%s_" % default) + "_".join(t.__name__ for t in types)    if hasattr(convert, "__qualname__"): convert.__qualname__ += namext    convert.__name__ += namext    return convert

Now tryconvert(0, int) returns a function convert_0_int that takes a value and converts it to an integer, and returns 0 if this can't be done. You can use this function right away (not saving a copy):

mynumber = tryconert(0, int)(value)

Or save it to call it later:

intconvert = tryconvert(0, int)# later...mynumber = intconvert(value)


In this specific instance, you can avoid using a try block like this:

lambda s: int(s) if s.isdigit() else 0

The isdigit() string method returns true if all the characters of s are digits. (If you need to accept negative numbers, you will have to do some extra checking.)


Yes, it is possible

I put together this little piece of code to demonstrate the possibility to catch exceptions and react to them inside a lambda. It's rather rudimentary and serves more or less as a proof of concept.

Example

>>> print_msg = lambda msg, **print_kwargs: \...   begin(...     print, msg, end='... ', **print_kwargs...   ).\...   rescue(...     (TypeError, AttributeError),...     lambda exc: print(f'just caught "{exc}"! how fun!')...   ).\...   ensure(print, 'ok done.')()>>> print_msg('check')check... ok done.>>> print_msg('check', file=1)just caught "'int' object has no attribute 'write'"! how fun!ok done.>>> print_msg('check', sep=1)just caught "sep must be None or a string, not int"! how fun!ok done.

A bit more practical example

modules = filter(None, (  begin(importlib.import_module, modname).rescue(lambda exc: None)()  for modname in module_names))


Code

from typing import Iterableclass begin:  def __init__(self, fun, *args, **kwargs):    self.fun = fun    self.args = args    self.kwargs = kwargs    self.exception_types_and_handlers = []    self.finalize = None  def rescue(self, exception_types, handler):    if not isinstance(exception_types, Iterable):      exception_types = (exception_types,)    self.exception_types_and_handlers.append((exception_types, handler))    return self  def ensure(self, finalize, *finalize_args, **finalize_kwargs):    if self.finalize is not None:      raise Exception('ensure() called twice')    self.finalize = finalize    self.finalize_args = finalize_args    self.finalize_kwargs = finalize_kwargs    return self  def __call__(self):    try:      return self.fun(*self.args, **self.kwargs)    except BaseException as exc:      handler = self.find_applicable_handler(exc)      if handler is None:        raise      return handler(exc)    finally:      if self.finalize is not None:        self.finalize()  def find_applicable_handler(self, exc):    applicable_handlers = (      handler      for exception_types, handler in self.exception_types_and_handlers      if isinstance(exc, exception_types)    )    return next(applicable_handlers, None)