【问题标题】:Why isn't the code in the `else` section of my `try` block being run?为什么我的 `try` 块的 `else` 部分中的代码没有运行?
【发布时间】:2014-03-31 14:24:36
【问题描述】:

我将 Python 2.7.3 与 Flask 0.10.1 和 SQL-Alchemy 0.9.1 一起使用。

在我的视图代码中,我正在构建一个用于数据库输入的对象,我的代码依赖于两个try/except/else 块的正确执行。它在第一个块中按预期工作,无论何时发生异常和没有异常。当出现异常时,我会得到errors 的集合。当没有异常时,数据被添加到数据库中并且样本计数器增加。这是sn-p:

        try:
            new_sample = Sample()
            new_sample.build(sample)
        except SampleBuildingError as e:
            result_response['errors'].append('{0}: {1}'.format(sample['sample_name'], e.value) )
        else:
            db.session.add(new_sample)
            num_added += 1

在视图函数的更下方,我有一个try/except/else/finally 块。数据正在提交到数据库,因此try 部分显然可以正常工作,finally 块也是如此。但是,else 块似乎没有被执行:

try:
    db.session.commit()
except Exception as e:
    result_response['error'] = "Failed on the database input: {0}".format( str(e) )
else:
    result_response['success'] = "The samples were input to the database successfully. {0} samples entered into the database, with {1} errors".format( num_added, len(errors) )
finally:
    return jsonify(result_response)

当出现异常时,我按预期返回带有 error 键和数据库错误的 json。但是,当数据库提交成功时,我会得到一个 json 对象,其中包含每个预期的键 除了 success 键。

似乎else 块被跳过,但我不知道为什么。我尝试在 else 块的第二行加上 bogus 这个词来尝试强制出错,但 Python 不会抱怨!

这是完整的视图功能:

@app.route("/kapasubmit", methods=['POST'])
def kapasubmit():
    num_added = 0
    result_response = {'errors': []}
    samples = request.json['data']
    for sample in samples:
        sample_check = Sample.query.filter_by( sample_name = sample['sample_name'] ).first()
        if sample_check is None:
            try:
                new_sample = Sample()
                new_sample.build(sample)
            except SampleBuildingError as e:
                result_response['errors'].append('{0}: {1}'.format(sample['sample_name'], e.value) )
            else:
                db.session.add(new_sample)
                num_added += 1
        else:
            result_response['errors'].append('{0}: This is a duplicate sample'.format(sample['sample_name']) )

    if num_added > 0:
        try:
            db.session.commit()
        except Exception as e:
            result_response['error'] = "Failed on the database input: {0}".format( str(e) )
        else:
            result_response['success'] = "The samples were input to the database successfully. {0} samples entered into the database, with {1} errors".format( num_added, len(errors) )
            bogus
        finally:
            return jsonify(result_response)
    else:
        result_response['error'] = "No valid samples submitted for input"
        return jsonify(result_response)

【问题讨论】:

  • 我做了一个快速测试,>>> try: ... pass ... except: ... pass ... else: ... print 'else' ... finally: ... print 'finally' ... else finally 这似乎有效。必须有别的东西。
  • @njzk2 是的,这令人费解,因为第一个语句完全按照它应该的方式工作。第二条语句有效,只是它跳过了 else 块。莫名其妙,尤其是对于 Python(但不是编码)新手。
  • 在这种特殊情况下,为什么不将语句放入 try 块中。根据stackoverflow.com/questions/855759/python-try-else,您唯一需要 else 的时间是当有一个您不想由您的 except 处理的异常引发案例时:在这种情况下,不需要 else。
  • len(errors):我没看到errors是在哪里定义的?
  • @sabbahillel 这是个好建议。但现在我想知道发生了什么,就我所知。

标签: python json exception-handling flask


【解决方案1】:

我认为errors 没有定义。

len(errors) 会引发异常,但不会阻止 finally 块的执行,因此仍会返回一些数据,而无需定义 result_response['success']

【讨论】:

  • 谢谢:我用 else 测试了这个: print 'in else', errors, 'out of else' finally: 'done' 和 'in else' 'done' 被打印出来,然后是 NameError 错误未定义输出。
  • 上述注释中的错字,每个字符串都应该有一个单独的打印,因为它是不可理解的,您可能需要添加一个代码 sn-p 来说明您的观点。
【解决方案2】:

如果else 块引发异常,它会被忽略,因为解释器必须从函数中执行return。一个演示:

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print "division by zero!"
...     else:
...         print "result is", result
...         print 1/0
...     finally:
...         return 1
... 
>>> divide(2,1)
result is 2
1

1/0 不会导致任何回溯。

【讨论】:

  • 这使得使用 returnfinally 非常危险,因为如果在 except 块中也引发了异常,结果没有任何不同。
  • 这是正确且有用的,谢谢! @njzk2 首先发现了错误,所以我想我必须给他检查。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-02
  • 1970-01-01
  • 2015-05-20
  • 1970-01-01
  • 2021-10-17
  • 2022-01-23
  • 2019-04-23
相关资源
最近更新 更多