for-loop / EAFP中的异常处理

时间:2014-04-29 02:49:31

标签: python exception exception-handling coding-style

我有一个带有JSON数据的请求,它可能包含或不包含'items'键,如果它必须是一个对象列表,我想单独处理。所以我必须写一些类似的东西:

json_data = request.get_json()
for item in json_data['items']:
    process_item(item)

但是,由于'items'密钥的存在不是强制性的,因此需要采取额外措施。我想遵循EAFP方法,将其包装到try ... except语句中:

json_data = request.get_json()
try:
    for item in json_data['items']:
        process_item(item)
except KeyError as e:
    pass

让我们假设KeyError函数内部可能发生process_item(...)异常,这可能表示代码错误,因此不应忽视它,所以我想确保我只会捕获异常来自for语句谓词,作为我提出的解决方法:

json_data = request.get_json()
try:
    for item in json_data['items']:
        process_item(item)
except KeyError as e:
    if e.message != 'items':
        raise e
    pass

但是

  1. 看起来很难看
  2. 它依赖于process_item(...)实现的知识,假设KeyError('items')无法在其中引发。
  3. 如果for语句变得更复杂,例如for json_data['raw']['items'] except条款也会使其更具可读性和可维护性。
  4. 更新 建议的备选方案

    json_data = request.get_json()
    try:
        items = json_data["items"]
    except KeyError:
        items = []
    
    for item in items:
        process_item(item)
    

    基本相同
    json_data = request.get_json()
    if json_data.has('items')
        items = json_data['items']
    else:
        items = []
    
    for item in items:
        process_item(item)
    

    所以我们在循环前检查。我想知道是否还有pythonic / EAFP方法?

2 个答案:

答案 0 :(得分:1)

只有在访问"items"时才能捕获异常:

json_data = request.get_json()
try:
    items = json_data["items"]
except KeyError:
    items = []
for item in items:
    process_item(item)

但是,我们可以通过调用.get()函数替换try-block,使其更清晰:

for item in request.get_json().get("items", []):
    process_item(item)

答案 1 :(得分:0)

我认为最干净的选择是仅在尝试检索与try密钥关联的数据的代码周围使用'items'块:

json_data = request.get_json()
try:
    items = json_data['items']
except KeyError:
    print "no 'items' to process"  # or whatever you want to...
else:
    for item in items:
        process_item(item)

此布局允许您根据需要明确区分错误处理。如果需要,您可以在try循环周围添加单独的独立except / for