简体   繁体   中英

Concise replacement for long list of Try-Except statement in Python?

I have this long list of try except statement:

    try:
       uri = entry_obj['media$group']['media$content'][0]['url']
    except (KeyError, IndexError):
       uri = None
    try:
       position = entry_obj['yt$position']['$t']
    except KeyError:
       position = None
    try:
       description = entry_obj['content']['$t']
    except KeyError:
       description = None
    try:
       seconds = entry_obj['media$group']['yt$duration']['seconds']
    except KeyError:
       seconds = None
    try:
       thumbnails = entry_obj['media$group']['media$thumbnail']
    except KeyError:
       thumbnails = None

Is there a more concise way to write this?

If you tire of figuring out what to use for default values in get() calls, just write a helper function:

def resolve(root, *keys):
   for key in keys:
       try:
           root = root[key]
       except (KeyError, IndexError):
           return None
   return root

Then you just write, eg:

uri = resolve(entry_obj, 'media$group', 'media$content', 0, 'url')

To simplify the calls a little, you might beef up the helper function to take a single string for the keys and split on spaces; that way you don't have to type so many quotes, and we can also add a default value argument:

def resolve(root, keys, default=None):
    for key in keys.split():
        try:
            root = root[key]
        except (TypeError, KeyError):
            try:
                root = root[int(key)]
            except (IndexError, ValueError, KeyError):
                return default

uri = resolve(entry_obj, 'media$group media$content 0 url', '')

I thought of another good way to do this, not sure how it compares to kindall's method. We first define a method property:

def res(self, property):
    try:
        return property()
    except (KeyError, IndexError):
        return None

Then replace the try-except statements with:

    url = res(lambda: entry_obj['media$group']['media$content'][0]['url'])
    position = res(lambda: entry_obj['yt$position']['$t'])
    description = res(lambda: entry_obj['content']['$t'])
    duration = res(lambda: entry_obj['media$group']['yt$duration']['seconds'])
    thumbnails = res(lambda: entry_obj['media$group']['media$thumbnail'])

Use the get method of dictionaries instead:

position = entry_object.get('yt$position').get('$t')

get will handle the case of a key not existing for you, and give you a (changable) fallback value instead in that case. You'll still need to handle the first IndexError manually, but all the ones that are just except KeyError: will disappear.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM