General decorator to wrap try except in python?

后端 未结 8 1717
庸人自扰
庸人自扰 2020-12-12 16:25

I\'d interacting with a lot of deeply nested json I didn\'t write, and would like to make my python script more \'forgiving\' to invalid input. I find myself writing involve

8条回答
  •  北荒
    北荒 (楼主)
    2020-12-12 16:36

    in your case you first evaluate the value of the meow call (which doesn't exist) and then wrap it in the decorator. this doesn't work that way.

    first the exception is raised before it was wrapped, then the wrapper is wrongly indented (silenceit should not return itself). You might want to do something like:

    def hardfail():
      return meow() # meow doesn't exist
    
    def f(func):
      def wrapper():
        try:
          func()
        except:
          print 'error'
      return wrapper
    
    softfail =f(hardfail)
    

    output:

    >>> softfail()
    error
    
    >>> hardfail()
    Traceback (most recent call last):
      File "", line 1, in 
      File "", line 2, in hardfail
    NameError: global name 'meow' is not defined
    

    anyway in your case I don't understand why you don't use a simple method such as

    def get_subkey(obj, key, subkey):
      try:
        return obj.get(key).get(subkey, '')
      except AttributeError:
        return ''
    

    and in the code:

     item['a'] = get_subkey(myobject, 'key', 'subkey')
    

    Edited:

    In case you want something that will work at any depth. You can do something like:

    def get_from_object(obj, *keys):
      try:
        value = obj
        for k in keys:
            value = value.get(k)
        return value
      except AttributeError:
        return ''
    

    That you'd call:

    >>> d = {1:{2:{3:{4:5}}}}
    >>> get_from_object(d, 1, 2, 3, 4)
    5
    >>> get_from_object(d, 1, 2, 7)
    ''
    >>> get_from_object(d, 1, 2, 3, 4, 5, 6, 7)
    ''
    >>> get_from_object(d, 1, 2, 3)
    {4: 5}
    

    And using your code

    item['a'] = get_from_object(obj, 2, 3) 
    

    By the way, on a personal point of view I also like @cravoori solution using contextmanager. But this would mean having three lines of code each time:

    item['a'] = ''
    with ignored(AttributeError):
      item['a'] = obj.get(2).get(3) 
    

提交回复
热议问题